public void CopyFrom(UTinyList other) { Clear(); Type = other.Type; foreach (var item in other) { Add(item); } }
void ICustomVisit <UTinyList> .CustomVisit(UTinyList value) { var index = ++VisitorContext.ArrayIndex; var defaultJsValue = GetDefaultJsValue(value.Type.Dereference(VisitorContext.Registry)); VisitorContext.Writer.Line($"var a{index} = [{string.Join(", ", Enumerable.Range(0, value.Count).Select(x => defaultJsValue).ToArray())}];"); value.Visit(new ListVisitor { VisitorContext = VisitorContext, Path = $"a{index}" }); VisitorContext.Writer.Line($"{Path}.{Property.Name} = a{index};"); }
public void Refresh(UTinyList defaultValue = null, bool skipTypeCheck = false) { var type = Type.Dereference(m_Registry); if (null == type) { return; } // Force the type to be refreshed if (!skipTypeCheck) { type.Refresh(); } if (m_CurrentTypeVersion == type.Version) { return; } // Migrate the values m_Items = MigrateListValue(m_Registry, this, m_Items as IList, type); // Rebuild the default value property if (null != m_ItemsProperty) { m_PropertyBag.RemoveProperty(m_ItemsProperty); } m_ItemsProperty = CreateItemsProperty(type); if (null != m_ItemsProperty) { m_PropertyBag.AddProperty(m_ItemsProperty); } m_CurrentTypeVersion = type.Version; }
/// <summary> /// This method does a lot of magic /// You can associate ANY value with a name and the correct property will be generated for you /// </summary> public object this[string key] { get { // Incurs a dictionary lookup var property = m_PropertyBag.FindProperty(key); // Must asset to avoid undefined behaviour Assert.IsNotNull(property, $"Property '{key}' does not exist on object"); var container = (IPropertyContainer)this; // This works well since the implementation details are abstracted // i.e. We don't care how the value is unpacked (List, Dictionary, NativeArray etc) return(property.GetObjectValue(container)); } set { // Incurs a dictionary lookup var property = m_PropertyBag.FindProperty(key); if (null == property) { // Auto-generate a dynamic property for the user var type = value?.GetType() ?? typeof(object); property = CreateDynamicProperty(key, type); Assert.IsNotNull(property); m_PropertyBag.AddProperty(property); if (null == m_DynamicValues) { m_DynamicValues = new Dictionary <string, object>(); } // Setup the underlying storage // This breaks our abstraction but must be done at some point if (typeof(UTinyObject) == type) { var obj = new UTinyObject(m_Object.Registry, UTinyType.Reference.None); obj.CopyFrom(value as UTinyObject); m_DynamicValues.Add(key, obj); } else if (typeof(UTinyList) == type) { var obj = new UTinyList(m_Object.Registry, UTinyType.Reference.None); obj.CopyFrom(value as UTinyList); m_DynamicValues.Add(key, obj); } else { m_DynamicValues.Add(key, value); } } else { // @TODO There is an unhandled case here when we encounter a type mis-match, we need to detect this and throw try { property.SetObjectValue(this, value); } catch (InvalidCastException) { Debug.LogError($"Could not cast {value.GetType()} to {property.ValueType}. Value is '{value}'."); throw; } } } }
public static object MigrateFieldValue(IRegistry registry, IVersionStorage versionStorage, object value, UTinyType type, bool array, object defaultValue = null, bool skipTypeCheck = false) { if (array) { var list = value as UTinyList; if (null == list) { list = new UTinyList(registry, versionStorage) { Type = (UTinyType.Reference)type }; list.Refresh(defaultValue as UTinyList, skipTypeCheck); } else { list.Type = (UTinyType.Reference)type; list.Refresh(defaultValue as UTinyList, skipTypeCheck); } return(list); } switch (type.TypeCode) { case UTinyTypeCode.Unknown: break; case UTinyTypeCode.Int8: return(TryChangeType <sbyte>(value)); case UTinyTypeCode.Int16: return(TryChangeType <short>(value)); case UTinyTypeCode.Int32: return(TryChangeType <int>(value)); case UTinyTypeCode.Int64: return(TryChangeType <long>(value)); case UTinyTypeCode.UInt8: return(TryChangeType <byte>(value)); case UTinyTypeCode.UInt16: return(TryChangeType <ushort>(value)); case UTinyTypeCode.UInt32: return(TryChangeType <uint>(value)); case UTinyTypeCode.UInt64: return(TryChangeType <ulong>(value)); case UTinyTypeCode.Float32: return(TryChangeType <float>(value)); case UTinyTypeCode.Float64: return(TryChangeType <double>(value)); case UTinyTypeCode.Boolean: return(TryChangeType <bool>(value)); case UTinyTypeCode.Char: return(TryChangeType <char>(value)); case UTinyTypeCode.String: return(TryChangeType <string>(value) ?? string.Empty); case UTinyTypeCode.Configuration: case UTinyTypeCode.Component: // Components can not be fields, they can only exist at the entity level throw new NotSupportedException(); case UTinyTypeCode.Struct: { var obj = value as UTinyObject; if (null == obj) { obj = new UTinyObject(registry, (UTinyType.Reference)type, versionStorage, false); obj.Refresh(defaultValue as UTinyObject, skipTypeCheck); } else { obj.Type = (UTinyType.Reference)type; obj.Refresh(defaultValue as UTinyObject, skipTypeCheck); } return(obj); } case UTinyTypeCode.Enum: { if (value is UTinyEnum.Reference) { return(new UTinyEnum.Reference(type, ((UTinyEnum.Reference)value).Id)); } return(defaultValue is UTinyEnum.Reference ? new UTinyEnum.Reference(type, ((UTinyEnum.Reference)defaultValue).Id) : new UTinyEnum.Reference(type, type.Fields.First().Id)); } case UTinyTypeCode.EntityReference: { if (value is UTinyEntity.Reference) { return(value); } return(defaultValue is UTinyEntity.Reference ? defaultValue : UTinyEntity.Reference.None); } case UTinyTypeCode.UnityObject: { if (value is Object) { return(value); } return(defaultValue is Object ? defaultValue : null); } default: throw new ArgumentOutOfRangeException(); } return(null); }
void ICustomVisit <UTinyList> .CustomVisit(UTinyList value) { throw new NotImplementedException(); }
bool IExcludeVisit <UTinyList> .ExcludeVisit(UTinyList value) { return(!IsListItem); }
bool IExcludeVisit <UTinyList> .ExcludeVisit(UTinyList value) { return(value.Count > 0); }