Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions UnityWeld/Binding/Adapters/StringArrayToListAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;

namespace UnityWeld.Binding.Adapters
{
/// <summary>
/// Adapter for converting from a string array to a string list.
/// </summary>
[Adapter(typeof(string[]), typeof(List<string>), null)]
public class StringArrayToListAdapter : IAdapter
{
public object Convert(object valueIn, AdapterOptions options)
{
List<string> output = new List<string>();

if(valueIn == null)
{
return output;
}
return new List<string>((string[])valueIn);
}
}
}
22 changes: 22 additions & 0 deletions UnityWeld/Binding/Adapters/StringListToArrayAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;

namespace UnityWeld.Binding.Adapters
{
/// <summary>
/// Adapter for converting from a string list to a string array.
/// </summary>
[Adapter(typeof(List<string>), typeof(string[]), null)]
public class StringListToArrayAdapter : IAdapter
{
public object Convert(object valueIn, AdapterOptions options)
{

if (valueIn == null)
{
return new string[0];
}

return ((List<string>)valueIn).ToArray();
}
}
}
45 changes: 37 additions & 8 deletions UnityWeld/Binding/DropdownBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ public class DropdownBinding : AbstractMemberBinding
/// <summary>
/// Name of the property in the view model to bind for the current selection.
/// </summary>
public string viewModelSelectionPropertyName;
[SerializeField]
private string viewModelSelectionPropertyName;

/// <summary>
/// Name of the property in the view model to bind for the list of options.
/// </summary>
public string viewModelOptionsPropertyName;
[SerializeField]
private string viewModelOptionsPropertyName;

/// <summary>
/// The name of the property to assign an exception to when adapter/validation fails.
Expand Down Expand Up @@ -57,7 +59,14 @@ public class DropdownBinding : AbstractMemberBinding
/// Adapter for converting the options list in the view model
/// to the correct format to display in the UI.
/// </summary>
public string optionsAdapter;
[SerializeField]
public string optionsViewAdapterTypeName;

/// <summary>
/// Option data to use for the options adapter
/// </summary>
[SerializeField]
public AdapterOptions optionsViewAdapterOptions;

/// <summary>
/// Cached drop down component.
Expand All @@ -68,8 +77,8 @@ public override void Connect()
{
dropdown = GetComponent<Dropdown>();

var selectionPropertyEndPoint = MakeViewModelEndPoint(viewModelSelectionPropertyName, selectionUIToViewModelAdapter, null);

var selectionPropertyEndPoint = MakeViewModelEndPoint(ViewModelSelectionPropertyName, selectionUIToViewModelAdapter, null);
var selectionPropertySync = new PropertySync(
// Source
selectionPropertyEndPoint,
Expand Down Expand Up @@ -101,20 +110,20 @@ public override void Connect()
"onValueChanged",
() =>
{
selectedOption = Options[dropdown.value]; // Copy value back from dropdown.
selectedOption = Options.Length > 0 ? Options[dropdown.value] : null; // Copy value back from dropdown.
selectionPropertySync.SyncFromDest();
}
);

var optionsPropertySync = new PropertySync(
// Source
MakeViewModelEndPoint(viewModelOptionsPropertyName, null, null),
MakeViewModelEndPoint(ViewModelOptionsPropertyName, null, null),

// Dest
new PropertyEndPoint(
this,
"Options",
CreateAdapter(optionsAdapter),
CreateAdapter(optionsViewAdapterTypeName),
null,
"view",
this
Expand Down Expand Up @@ -201,6 +210,24 @@ public string SelectedOption
}
}

public string ViewModelOptionsPropertyName
{
get { return viewModelOptionsPropertyName; }
set
{
viewModelOptionsPropertyName = value;
}
}

public string ViewModelSelectionPropertyName
{
get { return viewModelSelectionPropertyName; }
set
{
viewModelSelectionPropertyName = value;
}
}

/// <summary>
/// Update the options.
/// </summary>
Expand All @@ -209,6 +236,8 @@ private void UpdateOptions()
dropdown.options = options
.Select(option => new Dropdown.OptionData(option))
.ToList();

UpdateSelectedOption();
}

/// <summary>
Expand Down
150 changes: 150 additions & 0 deletions UnityWeld_Editor/DropdownBindingEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEngine;
using UnityWeld.Binding;
using UnityWeld.Binding.Internal;

namespace UnityWeld_Editor
{
[CustomEditor(typeof(DropdownBinding))]
public class DropdownBindingEditor : BaseBindingEditor
{
private DropdownBinding targetScript;

private readonly bool viewPropertyPrefabModified;
private AnimBool optionsAdapterOptionsFade;

private void OnEnable()
{
// Initialise reference to target script
targetScript = (DropdownBinding)target;

Type adapterType;

optionsAdapterOptionsFade = new AnimBool(
ShouldShowAdapterOptions(targetScript.optionsViewAdapterTypeName, out adapterType)
);

optionsAdapterOptionsFade.valueChanged.AddListener(Repaint);
}

private void OnDisable()
{
optionsAdapterOptionsFade.valueChanged.RemoveListener(Repaint);
}

public override void OnInspectorGUI()
{
UpdatePrefabModifiedProperties();

var defaultLabelStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = viewPropertyPrefabModified
? FontStyle.Bold
: defaultLabelStyle;

ShowViewModelPropertyMenu(
new GUIContent(
"Options: View-model property",
"Property on the view-model to bind Options to."
),
TypeResolver.FindBindableProperties(targetScript),
updatedValue => targetScript.ViewModelOptionsPropertyName = updatedValue,
targetScript.ViewModelOptionsPropertyName,
property => property.PropertyType == typeof(string[]) || property.PropertyType == typeof(System.Collections.Generic.List<string>)
);

Type viewPropertyType = typeof(string[]);

var viewAdapterTypeNames = GetAdapterTypeNames(
type =>
{
return viewPropertyType == null ||
TypeResolver.FindAdapterAttribute(type).OutputType == viewPropertyType;
});

var guiPreviouslyEnabled = GUI.enabled;

ShowAdapterMenu(
new GUIContent(
"View adapter",
"Adapter that converts values sent from the view-model to the view."
),
viewAdapterTypeNames,
targetScript.optionsViewAdapterTypeName,
newValue =>
{
// Get rid of old adapter options if we changed the type of the adapter.
if (newValue != targetScript.optionsViewAdapterTypeName)
{
Undo.RecordObject(targetScript, "Set view adapter options");
targetScript.optionsViewAdapterTypeName = null;
}

UpdateProperty(
updatedValue => targetScript.optionsViewAdapterTypeName = updatedValue,
targetScript.optionsViewAdapterTypeName,
newValue,
"Set view adapter"
);
}
);

Type adapterType;
optionsAdapterOptionsFade.target = ShouldShowAdapterOptions(
targetScript.optionsViewAdapterTypeName,
out adapterType
);

ShowAdapterOptionsMenu(
"View adapter options",
adapterType,
options => targetScript.optionsViewAdapterOptions = options,
targetScript.optionsViewAdapterOptions,
optionsAdapterOptionsFade.faded
);



ShowViewModelPropertyMenu(
new GUIContent(
"Selected Item : View-model property",
"Property on the view-model to bind the selected item to."
),
TypeResolver.FindBindableProperties(targetScript),
updatedValue => targetScript.ViewModelSelectionPropertyName = updatedValue,
targetScript.ViewModelSelectionPropertyName,
property => property.PropertyType == typeof(string)
);

GUI.enabled = guiPreviouslyEnabled;

EditorStyles.label.fontStyle = defaultLabelStyle;
}

/// <summary>
/// Check whether each of the properties on the object have been changed
/// from the value in the prefab.
/// </summary>
private void UpdatePrefabModifiedProperties()
{
var property = serializedObject.GetIterator();
// Need to call Next(true) to get the first child. Once we have it, Next(false)
// will iterate through the properties.
property.Next(true);
do
{
switch (property.name)
{

default:
//Debug.Log(property.name);
break;
}
}
while (property.Next(false));
}
}
}