// Amplify Shader Editor - Visual Shader Editing Tool
|
|
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
|
|
|
|
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
|
|
}
|
|
|
|
public enum AseOptionsType
|
|
{
|
|
Option,
|
|
Port
|
|
}
|
|
|
|
public enum AseOptionsActionType
|
|
{
|
|
ShowOption,
|
|
HideOption,
|
|
HidePort,
|
|
ShowPort,
|
|
SetDefine,
|
|
UnsetDefine,
|
|
ExcludePass
|
|
}
|
|
|
|
public enum AseOptionsSetup
|
|
{
|
|
CopyOptionsFromMainPass,
|
|
Id,
|
|
Name
|
|
}
|
|
|
|
[Serializable]
|
|
public class TemplateActionItem
|
|
{
|
|
public AseOptionsActionType ActionType;
|
|
public string ActionData = string.Empty;
|
|
public int ActionDataIdx = -1;
|
|
public override string ToString()
|
|
{
|
|
return ActionType + " " + ActionData + " " + ActionDataIdx;
|
|
}
|
|
}
|
|
|
|
[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 string Id = string.Empty;
|
|
public string Name = string.Empty;
|
|
public string DefaultOption = string.Empty;
|
|
public string[] Options = null;
|
|
|
|
public TemplateActionItemGrid ActionsPerOption = null;
|
|
|
|
[SerializeField]
|
|
private int m_defaultOptionIndex = -1;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
[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;
|
|
}
|
|
|
|
public class TemplateOptionsToolsHelper
|
|
{
|
|
public const string PassOptionsMainPattern = @"\/\*ase_pass_options:([\w:= ]*)[\n]([\w: \t;\n&|,_]*)\*\/";
|
|
public static Dictionary<string, AseOptionsSetup> AseOptionsSetupDict = new Dictionary<string, AseOptionsSetup>()
|
|
{
|
|
{ "CopyOptionsFromMainPass",AseOptionsSetup.CopyOptionsFromMainPass},
|
|
{ "Id",AseOptionsSetup.Id},
|
|
{ "Name",AseOptionsSetup.Name},
|
|
};
|
|
|
|
public static Dictionary<string, AseOptionsUIWidget> AseOptionsUITypeDict = new Dictionary<string, AseOptionsUIWidget>()
|
|
{
|
|
{ "Dropdown",AseOptionsUIWidget.Dropdown },
|
|
{ "Toggle", AseOptionsUIWidget.Toggle }
|
|
};
|
|
|
|
public static Dictionary<string, AseOptionsActionType> AseOptionsActionTypeDict = new Dictionary<string, AseOptionsActionType>()
|
|
{
|
|
{"ShowOption", AseOptionsActionType.ShowOption },
|
|
{"HideOption", AseOptionsActionType.HideOption },
|
|
{"HidePort", AseOptionsActionType.HidePort },
|
|
{"ShowPort", AseOptionsActionType.ShowPort },
|
|
{"SetDefine", AseOptionsActionType.SetDefine },
|
|
{"UnsetDefine", AseOptionsActionType.UnsetDefine },
|
|
{"ExcludePass", AseOptionsActionType.ExcludePass }
|
|
};
|
|
|
|
public static TemplateOptionsContainer GenerateOptionsContainer( string data )
|
|
{
|
|
TemplateOptionsContainer optionsContainer = new TemplateOptionsContainer();
|
|
|
|
Match match = Regex.Match( data, PassOptionsMainPattern );
|
|
optionsContainer.Enabled = match.Success;
|
|
if( match.Success )
|
|
{
|
|
optionsContainer.Body = match.Value;
|
|
optionsContainer.Index = match.Index;
|
|
|
|
List<TemplateOptionsItem> optionItemsList = new List<TemplateOptionsItem>();
|
|
List<List<TemplateActionItem>> actionItemsList = new List<List<TemplateActionItem>>();
|
|
Dictionary<string, int> optionItemToIndex = new Dictionary<string, int>();
|
|
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: int.TryParse(args[1], out optionsContainer.Id ) ; 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( ',' );
|
|
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;
|
|
currentOption.Name = optionItems[ 1 ];
|
|
currentOption.Id = itemIds.Length > 1? itemIds[1]:optionItems[ 1 ];
|
|
currentOption.Options = optionItems[ 2 ].Split( ',' );
|
|
for( int opIdx = 0; opIdx < currentOption.Options.Length; opIdx++ )
|
|
{
|
|
optionItemToIndex.Add( currentOption.Options[ opIdx ], opIdx );
|
|
actionItemsList.Add( new List<TemplateActionItem>() );
|
|
}
|
|
if( optionItems.Length > 3 )
|
|
{
|
|
currentOption.DefaultOption = optionItems[ 3 ];
|
|
}
|
|
else
|
|
{
|
|
currentOption.DefaultOption = currentOption.Options[ 0 ];
|
|
}
|
|
|
|
if( currentOption.Options.Length > 2 )
|
|
{
|
|
currentOption.UIWidget = AseOptionsUIWidget.Dropdown;
|
|
}
|
|
else if( currentOption.Options.Length == 2 )
|
|
{
|
|
if( ( currentOption.Options[ 0 ].Equals( "true" ) && currentOption.Options[ 1 ].Equals( "false" ) ) ||
|
|
( currentOption.Options[ 0 ].Equals( "false" ) && currentOption.Options[ 1 ].Equals( "true" ) ) )
|
|
{
|
|
currentOption.UIWidget = AseOptionsUIWidget.Toggle;
|
|
}
|
|
}
|
|
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;
|
|
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<TemplateActionItem>() );
|
|
actionItemsList.Add( new List<TemplateActionItem>() );
|
|
|
|
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;
|
|
}
|
|
else
|
|
{
|
|
idx = optionItemToIndex[ optionItems[ 0 ] ];
|
|
}
|
|
actionItemsList[ idx ].Add( CreateActionItem( 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( 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;
|
|
}
|
|
return optionsContainer;
|
|
}
|
|
|
|
static void FillOptionAction( TemplateOptionsItem currentOption, ref List<List<TemplateActionItem>> actionItemsList )
|
|
{
|
|
if( currentOption != null )
|
|
{
|
|
currentOption.ActionsPerOption = new TemplateActionItemGrid( actionItemsList.Count );
|
|
for( int i = 0; i < actionItemsList.Count; i++ )
|
|
{
|
|
currentOption.ActionsPerOption[ i ] = actionItemsList[ i ].ToArray();
|
|
actionItemsList[ i ].Clear();
|
|
}
|
|
actionItemsList.Clear();
|
|
}
|
|
}
|
|
|
|
static TemplateActionItem CreateActionItem( string[] optionItems )
|
|
{
|
|
TemplateActionItem actionItem = new TemplateActionItem();
|
|
actionItem.ActionType = AseOptionsActionTypeDict[ optionItems[ 1 ] ];
|
|
actionItem.ActionData = optionItems[ 2 ];
|
|
return actionItem;
|
|
}
|
|
}
|
|
}
|