Created
July 1, 2020 16:40
-
-
Save joethephish/2cecc517ef036c21dcc00f959740b519 to your computer and use it in GitHub Desktop.
Class to wrap single tweakable float value for UI that depends on platform. Could be hacked/adapted for something other than input type/platform.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
/// <summary> | |
/// PlatformFloat is an easy way of providing platform-specific tweak values. | |
/// By default, it behaves exactly like a normal float, and is converted back and forth | |
/// from a normal float implicitly. | |
/// However, in the inspector its possible to use a dropdown to provide platform | |
/// specific values for desktop, gamepad and touch. | |
/// </summary> | |
[Flags] | |
public enum PlatformValuePresence { | |
NonSpecific = 0, | |
Desktop = 1, | |
Gamepad = 2, | |
Mobile = 4, | |
All = ~0 | |
} | |
[Serializable] | |
public class PlatformFloat : ISerializationCallbackReceiver { | |
[SerializeField] PlatformValuePresence presence; | |
public float desktopAndFallbackValue; | |
public bool isNonSpecific { | |
get { | |
return presence == PlatformValuePresence.NonSpecific; | |
} | |
} | |
public bool hasDesktopValue { | |
get { return (presence & PlatformValuePresence.Desktop) > 0; } | |
set { | |
if( value ) | |
presence |= PlatformValuePresence.Desktop; | |
else | |
presence &= ~PlatformValuePresence.Desktop; | |
} | |
} | |
public float gamepadValue; | |
public bool hasGamepadValue { | |
get { return (presence & PlatformValuePresence.Gamepad) > 0; } | |
set { | |
if( value ) | |
presence |= PlatformValuePresence.Gamepad; | |
else | |
presence &= ~PlatformValuePresence.Gamepad; | |
} | |
} | |
public float mobileValue; | |
public bool hasMobileValue { | |
get { return (presence & PlatformValuePresence.Mobile) > 0; } | |
set { | |
if( value ) | |
presence |= PlatformValuePresence.Mobile; | |
else | |
presence &= ~PlatformValuePresence.Mobile; | |
} | |
} | |
public float current { get; private set; } | |
public void OnAfterDeserialize() { | |
RefreshCurrentValue(); | |
InputController.OnChangeInputTypeEarly -= OnChangeInput; | |
InputController.OnChangeInputTypeEarly += OnChangeInput; | |
} | |
PlatformFloat() { | |
RefreshCurrentValue(); | |
InputController.OnChangeInputTypeEarly -= OnChangeInput; | |
InputController.OnChangeInputTypeEarly += OnChangeInput; | |
} | |
~PlatformFloat() { | |
InputController.OnChangeInputTypeEarly -= OnChangeInput; | |
} | |
public void OnBeforeSerialize() { | |
} | |
void OnChangeInput(InputController.InputType newInputType) | |
{ | |
RefreshCurrentValue(); | |
} | |
void RefreshCurrentValue() | |
{ | |
current = ChooseCurrentValue(); | |
} | |
float ChooseCurrentValue() { | |
if( !InputController.IsInitialized ) return desktopAndFallbackValue; | |
var inputType = InputController.inputType; | |
if( inputType == InputController.InputType.KeyboardAndMouse ) { | |
if( isNonSpecific || hasDesktopValue ) | |
return desktopAndFallbackValue; | |
else if( hasGamepadValue ) | |
return gamepadValue; | |
else | |
return mobileValue; | |
} else if( inputType == InputController.InputType.Gamepad ) { | |
if( hasGamepadValue ) | |
return gamepadValue; | |
else if( hasDesktopValue || isNonSpecific ) | |
return desktopAndFallbackValue; | |
else | |
return mobileValue; | |
} else if( inputType == InputController.InputType.Touch ) { | |
if( hasMobileValue ) | |
return mobileValue; | |
else if( hasDesktopValue || isNonSpecific ) | |
return desktopAndFallbackValue; | |
else | |
return gamepadValue; | |
} | |
return desktopAndFallbackValue; | |
} | |
public static implicit operator float(PlatformFloat f) | |
{ | |
return f.current; | |
} | |
public static implicit operator PlatformFloat(float f) | |
{ | |
return new PlatformFloat { | |
presence = PlatformValuePresence.NonSpecific, | |
desktopAndFallbackValue = f | |
}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEditor; | |
using UnityEngine; | |
using System; | |
[CustomPropertyDrawer (typeof (PlatformFloat))] | |
public class PlatformFloatDrawer : PropertyDrawer | |
{ | |
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) { | |
EditorGUI.BeginProperty (position, label, property); | |
var labelWidth = EditorGUIUtility.labelWidth; | |
EditorGUI.LabelField(new Rect(position.x, position.y, labelWidth, position.height), property.displayName); | |
var presenceProperty = property.FindPropertyRelative("presence"); | |
var presence = (PlatformValuePresence) presenceProperty.intValue; | |
float x = labelWidth; | |
float contentWidth = position.width - labelWidth; | |
float dropdownWidth = 40; | |
float valuesWidth = contentWidth - dropdownWidth; | |
if( _popupStyle == null ) { | |
_popupStyle = new GUIStyle(EditorStyles.popup); | |
_popupStyle.margin.right = 0; | |
_popupStyle.fixedWidth = dropdownWidth; | |
} | |
var dropdownRect = new Rect(x + valuesWidth, position.y, dropdownWidth, position.height); | |
var newPresence = (PlatformValuePresence) EditorGUI.EnumFlagsField(dropdownRect, GUIContent.none, presence, _popupStyle); | |
if( newPresence != presence ) { | |
presenceProperty.intValue = (int) newPresence; | |
presence = newPresence; | |
} | |
bool hasDesktop = FlagsX.IsSet((int)presence, (int)PlatformValuePresence.Desktop); | |
bool hasGamepad = FlagsX.IsSet((int)presence, (int)PlatformValuePresence.Gamepad); | |
bool hasMobile = FlagsX.IsSet((int)presence, (int)PlatformValuePresence.Mobile); | |
int numVals = 0; | |
if( hasDesktop ) numVals++; | |
if( hasGamepad ) numVals++; | |
if( hasMobile ) numVals++; | |
// Using fallback "any" value? | |
bool isAny = false; | |
if( numVals == 0 ) { | |
isAny = true; | |
numVals = 1; | |
} | |
float singleValWidth = valuesWidth / numVals; | |
float iconWidth = 0; | |
if( !isAny ) { | |
iconWidth = 16; | |
if( _iconStyle == null ) { | |
_iconStyle = new GUIStyle(EditorStyles.label); | |
_iconStyle.padding = new RectOffset(0,0,0,0); | |
_iconStyle.margin = new RectOffset(0,0,0,0); | |
_iconStyle.fixedWidth = iconWidth; | |
} | |
if( _icons == null ) { | |
_icons = new GUIContent[3]; | |
_icons[0] = EditorGUIUtility.IconContent("BuildSettings.Standalone.Small"); | |
_icons[1] = EditorGUIUtility.IconContent("BuildSettings.PS4.Small"); | |
_icons[2] = EditorGUIUtility.IconContent("BuildSettings.iPhone.Small"); | |
} | |
} | |
if( _valueStyle == null ) | |
_valueStyle = new GUIStyle(EditorStyles.numberField); | |
_valueStyle.fixedWidth = singleValWidth - iconWidth; | |
for(int i=0; i<3; i++) { | |
bool has; | |
string propertyName; | |
if( i == 0 ) { | |
has = hasDesktop || isAny; // desktop or fallback | |
propertyName = "desktopAndFallbackValue"; | |
} else if( i == 1 ) { | |
has = hasGamepad; | |
propertyName = "gamepadValue"; | |
} else { | |
has = hasMobile; | |
propertyName = "mobileValue"; | |
} | |
if( has ) { | |
if( !isAny ) | |
EditorGUI.LabelField(new Rect(x, position.y, iconWidth, position.height), _icons[i], _iconStyle); | |
var floatProp = property.FindPropertyRelative (propertyName); | |
floatProp.floatValue = EditorGUI.FloatField(new Rect(x+iconWidth, position.y, singleValWidth-iconWidth, position.height), floatProp.floatValue, _valueStyle); | |
x += singleValWidth; | |
} | |
} | |
EditorGUIUtility.labelWidth = 0; | |
EditorGUI.EndProperty(); | |
} | |
static GUIStyle _popupStyle; | |
static GUIStyle _valueStyle; | |
static GUIStyle _iconStyle; | |
static GUIContent[] _icons; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment