public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) { Material material = materialEditor.target as Material; var materials = materialEditor.targets.Cast <Material>(); InitCachedPropGroups(properties, material); EditorGUI.BeginChangeCheck(); DrawSelectionMode(); var updateSelectionMode = EditorGUI.EndChangeCheck(); string disabledPropHeader = "*"; bool insideBoxLayout = false; _currentMaterialSelectedProps.Clear(); _selectablePropertyCount = 0; string propHeader = null; foreach (var prop in properties) { if (prop.flags == MaterialProperty.PropFlags.HideInInspector || prop.flags == MaterialProperty.PropFlags.PerRendererData) { continue; } if (_reflectionHelper.IsHeader(prop, material.shader)) { if (insideBoxLayout) { EditorGUILayout.Separator(); EditorGUILayout.EndVertical(); insideBoxLayout = false; } EditorGUILayout.BeginVertical(KamakuraInspectorUtility.BoxScopeStyle); insideBoxLayout = true; } var propFlagsHolder = _reflectionHelper.GetPropertyDrawer <MaterialKSFlagsDecorator>(prop, material.shader) ?? _defaultFlags; var selectable = !propFlagsHolder.IsFlagSet(KSFlags.NonSelectable); bool wasSelected = false; if (propFlagsHolder.IsFlagSet(KSFlags.EnableFlag)) { if (!_cachedDisabledPropHeader.TryGetValue(prop.name, out propHeader)) { propHeader = prop.name.Replace("_Enable", "_"); _cachedDisabledPropHeader[prop.name] = propHeader; } bool isParamPropEnabled = !Mathf.Approximately(prop.floatValue, 0f); disabledPropHeader = isParamPropEnabled ? "*" : propHeader; } if (_selectPropertyMode && selectable) { if (_selectionMode == SelectionMode.SelectAll) { _selectedProperties.Add(prop.name); } wasSelected = _selectedProperties.Contains(prop.name); _selectablePropertyCount += 1; if (wasSelected) { _currentMaterialSelectedProps.Add(prop.name); } } var isDisabled = prop.name.StartsWith(disabledPropHeader, System.StringComparison.Ordinal); if (isDisabled) { continue; } if (_selectPropertyMode && selectable) { GUI.color = wasSelected ? Color.green : Color.white; EditorGUILayout.BeginHorizontal(KamakuraInspectorUtility.SmallBoxScopeStyle); bool isSelected = EditorGUILayout.Toggle(wasSelected, EditorStyles.radioButton, GUILayout.MaxWidth(20), GUILayout.ExpandHeight(true)); if (isSelected) { _selectedProperties.Add(prop.name); } else { _selectedProperties.Remove(prop.name); } if (isSelected != wasSelected && Event.current.alt) { UpdateSelectionPropsWithHeader(prop.name, properties, isSelected); } GUI.color = Color.white; } else { EditorGUILayout.BeginHorizontal(); } MaterialPropertyUtils.BeginChangeCheck(prop); if (prop.name.Contains("UseCubeColor")) { var disabled = materials.Any(m => m.GetFloat("_EnableCubeColor") == 0); using (new EditorGUI.DisabledGroupScope(disabled)) { materialEditor.ShaderProperty(prop, prop.displayName); } } else { materialEditor.ShaderProperty(prop, prop.displayName); } var propChanged = MaterialPropertyUtils.EndChangeCheck(); if (propChanged && propFlagsHolder.IsFlagSet(KSFlags.AutoRenderQueue) && !prop.hasMixedValue && prop.floatValue > 0f) { foreach (var mat in materials) { var blendMode = (KamakuraBlendMode)(int)mat.GetFloat("_BlendMode"); MaterialBlendModeUtils.SetMaterialBlendMode(mat, blendMode, true); } } EditorGUILayout.EndHorizontal(); // TODO find better way to display this description if (prop.name.Contains("_CubeColor5")) { EditorGUILayout.Separator(); EditorGUILayout.LabelField("CubeColor works on world space by default."); EditorGUILayout.LabelField("Attach a CubeColorLocalSpaceRoot component"); EditorGUILayout.LabelField("to make it works locally relative to the root."); } } if (insideBoxLayout) { EditorGUILayout.Separator(); EditorGUILayout.EndVertical(); insideBoxLayout = false; } materialEditor.RenderQueueField(); materialEditor.EnableInstancingField(); if (updateSelectionMode) { if (_selectionMode == SelectionMode.Copy) { _copiedProperties.Clear(); foreach (var propName in _currentMaterialSelectedProps) { var prop = properties.FirstOrDefault(p => p.name == propName); if (prop != null) { _copiedProperties[propName] = prop; } else { Debug.LogWarning("Could not copy property " + propName + " from current material"); } } } else if (_selectionMode == SelectionMode.Paste) { foreach (var selectedPropName in _selectedProperties) { MaterialProperty copiedProp; if (_copiedProperties.TryGetValue(selectedPropName, out copiedProp)) { var targetProp = properties.FirstOrDefault(p => p.name == selectedPropName); if (targetProp == null) { Debug.LogWarning("Could not paste copied property " + selectedPropName + " to current material"); continue; } targetProp.floatValue = copiedProp.floatValue; targetProp.colorValue = copiedProp.colorValue; targetProp.vectorValue = copiedProp.vectorValue; targetProp.textureValue = copiedProp.textureValue; targetProp.textureScaleAndOffset = copiedProp.textureScaleAndOffset; _reflectionHelper.ApplyMaterialPropertyHandler(targetProp, material.shader); } } } else if (_selectionMode == SelectionMode.Clear) { _selectedProperties.Clear(); _copiedProperties.Clear(); } } }
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) { Material material = materialEditor.target as Material; var materials = materialEditor.targets.Cast <Material>(); RichLabel = new GUIStyle(EditorStyles.boldLabel); RichLabel.richText = true; EditorGUI.BeginChangeCheck(); DrawSelectionMode(); var updateSelectionMode = EditorGUI.EndChangeCheck(); string disabledPropHeader = "N/A"; bool insideBoxLayout = false; _currentMaterialSelectedProps.Clear(); _selectablePropertyCount = 0; foreach (var prop in properties) { if (prop.flags == MaterialProperty.PropFlags.HideInInspector || prop.flags == MaterialProperty.PropFlags.PerRendererData) { continue; } string propHeader = null; if (_reflectionHelper.IsHeader(prop, material.shader)) { if (insideBoxLayout) { EditorGUILayout.Separator(); EditorGUILayout.EndVertical(); insideBoxLayout = false; } EditorGUILayout.BeginVertical(KamakuraInspectorUtility.BoxScopeStyle); insideBoxLayout = true; } if (_dict.TryGetValue(prop.name, out propHeader)) { bool isParamPropEnabled = !Mathf.Approximately(prop.floatValue, 0f); disabledPropHeader = isParamPropEnabled ? "N/A" : propHeader; } var selectable = prop.name != "_ShaderVersion"; bool wasSelected = false; bool selectAll = _selectionMode == SelectionMode.SelectAll; if (_selectPropertyMode && selectable) { if (selectAll) { _selectedProperties.Add(prop.name); } wasSelected = _selectedProperties.Contains(prop.name); _selectablePropertyCount += 1; if (wasSelected) { _currentMaterialSelectedProps.Add(prop.name); } } var isDisabled = prop.name.StartsWith(disabledPropHeader); if (isDisabled) { continue; } if (_selectPropertyMode && selectable) { GUI.color = wasSelected ? Color.green : Color.white; EditorGUILayout.BeginHorizontal(KamakuraInspectorUtility.SmallBoxScopeStyle); bool isSelected = EditorGUILayout.Toggle(wasSelected, EditorStyles.radioButton, GUILayout.MaxWidth(20), GUILayout.ExpandHeight(true)); if (isSelected) { _selectedProperties.Add(prop.name); } else { _selectedProperties.Remove(prop.name); } GUI.color = Color.white; } else { EditorGUILayout.BeginHorizontal(); } if (prop.name.Contains("UseCubeColor")) { var disabled = materials.Any(m => m.GetFloat("_EnableCubeColor") == 0); using (new EditorGUI.DisabledGroupScope(disabled)) { materialEditor.ShaderProperty(prop, prop.displayName); } } else { materialEditor.ShaderProperty(prop, prop.displayName); } EditorGUILayout.EndHorizontal(); // TODO find better way to display this description if (prop.name.Contains("_CubeColor5")) { EditorGUILayout.Separator(); EditorGUILayout.LabelField("CubeColor works on world space by default."); EditorGUILayout.LabelField("Attach a CubeColorLocalSpaceRoot component"); EditorGUILayout.LabelField("to make it works locally relative to the root."); } } if (insideBoxLayout) { EditorGUILayout.Separator(); EditorGUILayout.EndVertical(); insideBoxLayout = false; } materialEditor.RenderQueueField(); materialEditor.EnableInstancingField(); if (updateSelectionMode) { if (_selectionMode == SelectionMode.Copy) { _copiedProperties.Clear(); foreach (var propName in _currentMaterialSelectedProps) { var prop = properties.FirstOrDefault(p => p.name == propName); if (prop != null) { _copiedProperties[propName] = prop; } else { Debug.LogWarning("Could not copy property " + propName + " from current material"); } } } else if (_selectionMode == SelectionMode.Paste) { foreach (var selectedPropName in _selectedProperties) { MaterialProperty copiedProp; if (_copiedProperties.TryGetValue(selectedPropName, out copiedProp)) { var targetProp = properties.FirstOrDefault(p => p.name == selectedPropName); if (targetProp == null) { Debug.LogWarning("Could not paste copied property " + selectedPropName + " to current material"); continue; } targetProp.floatValue = copiedProp.floatValue; targetProp.colorValue = copiedProp.colorValue; targetProp.vectorValue = copiedProp.vectorValue; targetProp.textureValue = copiedProp.textureValue; targetProp.textureScaleAndOffset = copiedProp.textureScaleAndOffset; _reflectionHelper.ApplyMaterialPropertyHandler(targetProp, material.shader); } } } else if (_selectionMode == SelectionMode.Clear) { _selectedProperties.Clear(); _copiedProperties.Clear(); } } }