public static RoadEditorCollapsiblePanel GetGroupPanel(this RoadEditorPanel instance, string name) { return ((RoadEditorCollapsiblePanel) GetMethod("GetGroupPanel") .Invoke(instance, new[] { name })); }
public static BitMaskPanel Add( RoadEditorPanel roadEditorPanel, UIComponent container, string label, Type enumType, SetHandlerD setHandler, GetHandlerD getHandler, string hint) { Log.Debug($"BitMaskPanel.Add(container:{container}, label:{label}, enumType:{enumType})"); var subPanel = UIView.GetAView().AddUIComponent(typeof(BitMaskPanel)) as BitMaskPanel; subPanel.EnumType = enumType; subPanel.SetHandler = setHandler; subPanel.GetHandler = getHandler; subPanel.Initialize(); subPanel.Label.text = label + ":"; subPanel.Hint = hint; //if (dark) // subPanel.opacity = 0.1f; //else // subPanel.opacity = 0.3f; container.AttachUIComponent(subPanel.gameObject); roadEditorPanel.FitToContainer(subPanel); return(subPanel); }
internal static BitMaskPanel Add( RoadEditorPanel roadEditorPanel, UIComponent container, string label, string hint, FlagDataT flagData) { try { Log.Debug($"BitMaskPanel.Add(container:{container}, label:{label}, enumType:{flagData.EnumType})"); var subPanel = UIView.GetAView().AddUIComponent(typeof(BitMaskPanel)) as BitMaskPanel; subPanel.FlagData = flagData; subPanel.Target = roadEditorPanel.GetTarget(); subPanel.Label.text = label + ":"; subPanel.Hint = hint; subPanel.Initialize(); container.AttachUIComponent(subPanel.gameObject); roadEditorPanel.FitToContainer(subPanel); subPanel.EventPropertyChanged += roadEditorPanel.OnObjectModified; return(subPanel); } catch (Exception ex) { Log.Exception(ex); return(null); } }
public static void Postfix(RoadEditorPanel __instance, object ___m_Target) { if (___m_Target == null) { throw new ArgumentNullException("___m_Target"); } object target = ___m_Target; //Log.Debug($"AddCustomFields.PostFix() target={target}\n" + Environment.StackTrace); if (!(target is IInfoExtended)) { return;// handle extended target. } if (target is NetInfo.Segment) { __instance.AddCrossImportField(); __instance.AddModelImportField(true); } else if (target is NetInfo.Node) { __instance.AddCrossImportField(); __instance.AddModelImportField(false); } else if (target is NetInfo.Lane) { __instance.AddLanePropFields(); } else if (target is NetLaneProps.Prop) { __instance.AddLanePropSelectField(); } }
public static void AddToArrayField(this RoadEditorPanel instance, RoadEditorCollapsiblePanel panel, object element, FieldInfo field, object targetObject) { // private void AddToArrayField(RoadEditorCollapsiblePanel panel, // object element, FieldInfo field, object targetObject) GetMethod("AddToArrayField") .Invoke(instance, new[] { panel, element, field, targetObject }); }
public static void Postfix(RoadEditorPanel __instance) { try { __instance.m_Container.scrollWheelDirection = UIOrientation.Vertical; } catch (Exception e) { Log.Exception(e); } }
public static void Postfix(RoadEditorPanel __instance) { foreach (UIComponent uicomponent in __instance.m_Container.components) { if (uicomponent is IDataUI dataUI) { dataUI.Refresh(); } } }
public static void CreateGenericComponentExt( RoadEditorPanel roadEditorPanel, string groupName, object target, object metadata, FieldInfo extensionField) { if (TryGetMerge(extensionField, target, out var vanillaRequired, out var vanillaForbidden)) { CreateMergedComponent( roadEditorPanel: roadEditorPanel, groupName: groupName, fieldInfo: extensionField, metadata: metadata, mergedFieldRequired: vanillaRequired, mergedFieldForbidden: vanillaForbidden, mergedTarget: target); }
public static void Postfix( string name, FieldInfo field, object target, RoadEditorPanel __instance, object ___m_Target) { target ??= ___m_Target; RoadEditorCollapsiblePanel groupPanel = __instance.GetGroupPanel(name); if (name == "Props") { Log.Debug("creating `Add from template` button"); var button = groupPanel.m_Panel.AddUIComponent <EditorButon>(); button.zOrder = int.MaxValue; button.text = "Add from template"; button.width = 200; button.eventClicked += OnLoadFromTempalteClicked; } }
/// <summary> /// replace built-in fields /// </summary> public static bool Prefix(RoadEditorPanel __instance, ref string groupName, FieldInfo field, object target) { try { if (field == typeof(NetInfo.Node).GetField(nameof(NetInfo.Node.m_directConnect))) { groupName = NetInfoExtionsion.Node.DC_GROUP_NAME; } else if (field == typeof(NetInfo.Node).GetField(nameof(NetInfo.Node.m_connectGroup))) { groupName = NetInfoExtionsion.Node.DC_GROUP_NAME; } if (ModSettings.ARMode && field.FieldType == typeof(NetInfo.ConnectGroup)) { CreateConnectGroupComponent(__instance, groupName, target, field); return(false); } else { } if (IsUIReplaced(field)) { if (VanillaCanMerge(field)) { return(false); // will be merged with AR dd later } var container = GetContainer(__instance, groupName); var uidata = GetVanillaFlagUIData(field, target); //Log.Info($"[P1] CreateGenericField.Prefix() : field:{field}, target:{target}, group:{groupName}"); var bitMaskPanel = BitMaskPanel.Add( roadEditorPanel: __instance, container: container, label: uidata.Label, hint: uidata.Hint, flagData: uidata.FlagData); return(false); } return(true); } catch (Exception ex) { ex.Log(); return(false); } }
/// <summary> /// replace built-in fields /// </summary> public static bool Prefix(string groupName, FieldInfo field, object target, RoadEditorPanel __instance) { if (NetInfoExtionsion.EditedNetInfo == null) { return(true); // ignore this outside of asset editor. } if (RoadEditorPanelExtensions.RequiresUserFlag(field.FieldType)) { return(true); } if (field.HasAttribute <BitMaskAttribute>() && field.HasAttribute <CustomizablePropertyAttribute>()) { UIComponent container = __instance.m_Container; if (!string.IsNullOrEmpty(groupName)) { container = __instance.GetGroupPanel(groupName).Container; } var att = field.GetAttribute <CustomizablePropertyAttribute>(); var enumType = field.FieldType; enumType = HintExtension.GetMappedEnumWithHints(enumType); var hints = field.GetHints(); if (field.Name == "m_stopType") { hints.Add("set this for the pedestrian lane that contains the bus/tram stop."); } hints.AddRange(enumType.GetHints()); string hint = hints.JoinLines(); Log.Debug($"{field} -> hint is: " + hint); var bitMaskPanel = BitMaskPanel.Add( roadEditorPanel: __instance, container: container, label: att.name, enumType: enumType, setHandler: val => field.SetValue(target, val), getHandler: () => (int)field.GetValue(target), hint: hint); return(false); } return(true); }
public static RangePanel Add( RoadEditorPanel roadEditorPanel, UIComponent container, string label, object target, FieldInfo fieldInfo) { Log.Debug($"RangePanel.Add(container:{container}, label:{label})"); var subPanel = UIView.GetAView().AddUIComponent(typeof(RangePanel)) as RangePanel; subPanel.fieldInfo_ = fieldInfo; subPanel.target_ = target; subPanel.Initialize(); subPanel.Label.text = label + ":"; container.AttachUIComponent(subPanel.gameObject); roadEditorPanel.FitToContainer(subPanel); return(subPanel); }
public static ButtonPanel Add( RoadEditorPanel roadEditorPanel, UIComponent container, string label, string hint, Action action) { Log.Debug($"ButtonPanel.Add(container:{container}, label:{label})"); var subPanel = UIView.GetAView().AddUIComponent(typeof(ButtonPanel)) as ButtonPanel; subPanel.Enable(); subPanel.Button.text = label; subPanel.hint_ = hint; subPanel.Button.eventClick += (_, __) => action(); container.AttachUIComponent(subPanel.gameObject); roadEditorPanel.FitToContainer(subPanel); return(subPanel); }
internal static MultiBitMaskPanel Add( RoadEditorPanel roadEditorPanel, UIComponent container, string label, string hint, params FlagDataT[] flagDatas) { Log.Debug($"BitMaskPanel.Add(container:{container}, label:{label})"); var subPanel = UIView.GetAView().AddUIComponent(typeof(MultiBitMaskPanel)) as MultiBitMaskPanel; subPanel.FlagDatas = flagDatas; subPanel.Label.text = label + ":"; subPanel.Hint = hint; subPanel.Target = roadEditorPanel.GetTarget(); subPanel.Initialize(); container.AttachUIComponent(subPanel.gameObject); roadEditorPanel.FitToContainer(subPanel); subPanel.EventPropertyChanged += roadEditorPanel.OnObjectModified; return(subPanel); }
public static void AddModelImportField(this RoadEditorPanel instance, bool showColorField = true) => GetMethod("AddModelImportField") .Invoke(instance, new object[] { showColorField });
public static object GetTarget(this RoadEditorPanel instance) => ReflectionHelpers.GetFieldValue(instance, "m_Target");
public static void Reset(this RoadEditorPanel instance) => instance.Initialize(instance.GetTarget());
public static void DestroySidePanel(this RoadEditorPanel instance) => GetMethod("DestroySidePanel").Invoke(instance, null);
public static RoadEditorPanel GetSidePanel(this RoadEditorPanel instance) => ReflectionHelpers.GetFieldValue(instance, "m_SidePanel") as RoadEditorPanel;
public QuayRoadsPanelField(NetInfo netInfo, int sectionIndex, FieldInfo fieldInfo, IConvertible flag, UIPanel parent, RoadEditorPanel parentPanel) { netInfo_ = netInfo; sectionIndex_ = sectionIndex; fieldInfo_ = fieldInfo; flag_ = flag; parentPanel_ = parentPanel; if (flag_ is not null) { Log.Debug(flag.ToString()); Log.Debug(flag.ToUInt64().ToString()); var propertyCheckbox = parent.AddUIComponent <UICheckBoxExt>(); propertyCheckbox.Label = ""; propertyCheckbox.width = 20f; propertyCheckbox.isChecked = (AssetValue as IConvertible).IsFlagSet(flag); propertyCheckbox.eventCheckChanged += (_, _isChecked) => { //TODO: find a better / more robust way to do this. if (_isChecked) { if (Enum.GetUnderlyingType(fieldInfo_.FieldType) == typeof(Int32)) { AssetValue = (AssetValue as IConvertible).ToInt32(CultureInfo.InvariantCulture) | flag.ToInt32(CultureInfo.InvariantCulture); } else { AssetValue = (AssetValue as IConvertible).ToInt64() | flag.ToInt64(); } } else { if (Enum.GetUnderlyingType(fieldInfo_.FieldType) == typeof(Int32)) { AssetValue = (AssetValue as IConvertible).ToInt32(CultureInfo.InvariantCulture) & ~flag.ToInt32(CultureInfo.InvariantCulture); } else { AssetValue = (AssetValue as IConvertible).ToInt64() & ~flag.ToInt64(); } } }; } else { // TODO: right now, this assumes everything that is not a flags enum is a float // TODO: find a better way to create a text field - maybe something similar to UICheckBoxExt from KianCommons? var propertyHelper = new UIHelper(parent); var propertyTextField = propertyHelper.AddTextfield("wawa", (AssetValue as float?).ToString(), (_) => { }, (_) => { }) as UITextField; var labelObject = parent.Find <UILabel>("Label"); labelObject.parent.RemoveUIComponent(labelObject); Destroy(labelObject.gameObject); (propertyTextField.parent as UIPanel).autoFitChildrenHorizontally = true; (propertyTextField.parent as UIPanel).autoFitChildrenVertically = true; propertyTextField.numericalOnly = true; propertyTextField.allowFloats = true; propertyTextField.allowNegative = true; propertyTextField.eventTextSubmitted += (_, value) => { float newValue = (float)LenientStringToDouble(value, (double)(float)AssetValue); propertyTextField.text = newValue.ToString(); if (newValue != (float)AssetValue) { AssetValue = newValue; } }; } }
/// <summary> /// Adds new custom fields after a built-in field. /// or modify the name of the built-in fields /// </summary> public static void Postfix(string groupName, FieldInfo field, object target, RoadEditorPanel __instance) { try { if (target is NetLaneProps.Prop prop) { Log.Debug($"{__instance.name}.CreateGenericField.Postfix({groupName},{field},{target})" /* + Environment.StackTrace*/); if (ModSettings.ARMode) { var metadata = prop.GetOrCreateMetaData(); foreach (var field2 in field.GetAfterFields(metadata)) { CreateGenericComponentExt( roadEditorPanel: __instance, groupName: groupName, target: target, metadata: metadata, extensionField: field2); } } if (typeof(NetInfoExtionsion.LaneProp).ComesAfter(field)) { Assert(prop.LocateEditProp(out _, out var lane), "could not locate prop"); bool forward = lane.IsGoingForward(); bool backward = lane.IsGoingBackward(); bool unidirectional = forward || backward; if (!unidirectional) { ButtonPanel.Add( roadEditorPanel: __instance, container: __instance.m_Container, label: "Switch Forward/Backward", null, action: () => { prop.ToggleForwardBackward(); __instance.OnObjectModified(); __instance.Reset(); }); } ButtonPanel.Add( roadEditorPanel: __instance, container: __instance.m_Container, label: "Switch RHT/LHT", HintExtension.GetHintSwichLHT_RHT(unidirectional), action: () => { prop.ToggleRHT_LHT(unidirectional); __instance.OnObjectModified(); __instance.Reset(); }); } ReplaceLabel(__instance, "Start Flags Required:", "Tail Node Flags Required:"); ReplaceLabel(__instance, "Start Flags Forbidden:", "Tail Node Flags Forbidden:"); ReplaceLabel(__instance, "End Flags Required:", "Head Node Flags Required:"); ReplaceLabel(__instance, "End Flags Forbidden:", "Head Node Flags Forbidden:"); } else if (target is NetInfo.Node node) { Log.Debug($"{__instance.name}.CreateGenericField.Postfix({groupName},{field},{target})" /* + Environment.StackTrace*/); if (ModSettings.ARMode) { var metadata = node.GetOrCreateMetaData(); foreach (var field2 in field.GetAfterFields(metadata)) { CreateGenericComponentExt( roadEditorPanel: __instance, groupName: groupName, target: target, metadata: metadata, extensionField: field2); } } } else if (target is NetInfo.Segment segment) { Log.Debug($"{__instance.name}.CreateGenericField.Postfix({groupName}, {field}, {target})" /* + Environment.StackTrace*/); if (ModSettings.ARMode) { var metadata = segment.GetOrCreateMetaData(); AssertNotNull(metadata, $"{segment}"); foreach (var field2 in field.GetAfterFields(metadata)) { CreateGenericComponentExt( roadEditorPanel: __instance, groupName: groupName, target: target, metadata: metadata, extensionField: field2); } } } else if (target is NetInfo netInfo) { if (ModSettings.ARMode) { ReplaceLabel(__instance, "Pavement Width", "Pavement Width Left"); var net = netInfo.GetOrCreateMetaData(); AssertNotNull(net, $"{netInfo}"); foreach (var field2 in net.GetFieldsWithAttribute <CustomizablePropertyAttribute>()) { if (field2.ComesAfter(field)) { Log.Debug($"calling {__instance.name}.CreateGenericField({groupName},{field2},{net}) ..."); __instance.CreateGenericField(groupName, field2, net); } } if (field.Name == nameof(NetInfo.m_surfaceLevel)) { Log.Debug("adding QuayRoads button"); var qrButtonPanel = ButtonPanel.Add( roadEditorPanel: __instance, container: __instance.GetGroupPanel("Properties").m_Panel, label: "Edit QuayRoads profile", hint: "", action: () => QuayRoadsPanel.GetOrOpen(netInfo, __instance)); qrButtonPanel.EventDestroy += (_, _) => { QuayRoadsPanel.CloseIfOpen(netInfo); }; } } } } catch (Exception e) { Log.Exception(e); } }
public static void OnObjectModified(this RoadEditorPanel instance) => GetMethod("OnObjectModified").Invoke(instance, null);
/// <summary> /// /// </summary> /// <param name="groupName"></param> /// <param name="fieldInfo"></param> /// <param name="target"></param> /// <param name="instance"></param> /// <param name="prefix"></param> public static void CreateExtendedComponent( string groupName, FieldInfo fieldInfo, object target, RoadEditorPanel instance, string prefix = "") { //Assert(string.IsNullOrEmpty(groupName), "groupName is empty"); UIComponent container = instance.m_Container; //instance.component.GetComponentInChildren<UIScrollablePanel>(); if (!string.IsNullOrEmpty(groupName)) { container = instance.GetGroupPanel(groupName).Container; } AssertNotNull(container, "container"); Log.Debug("CreateExtendedComponent():container=" + container); Assert(fieldInfo.HasAttribute <CustomizablePropertyAttribute>(), "HasAttribute:CustomizablePropertyAttribute"); AssertNotNull(target, "target"); AssertNotNull(target, "fieldInfo"); AssertNotNull(target, "RoadEditorPanel instance"); Log.Debug( $"CreateExtendedComponent(groupName={groupName}, fieldInfo={fieldInfo}, target={target}, instance={instance.name}) called", false); var att = fieldInfo.GetAttribute <CustomizablePropertyAttribute>(); var optionals = fieldInfo.GetAttributes <OptionalAttribute>(); var optionals2 = target.GetType().GetAttributes <OptionalAttribute>(); foreach (var optional in optionals.Concat(optionals2)) { if (optional != null && !ModSettings.GetOption(optional.Option)) { Log.Debug($"Hiding {target.GetType().Name}::`{att.name}` because {optional.Option} is disabled"); return; } } var hints = fieldInfo.GetHints(); hints.AddRange(fieldInfo.FieldType.GetHints()); string hint = hints.JoinLines(); Log.Debug("hint is " + hint); if (fieldInfo.FieldType.HasAttribute <FlagPairAttribute>()) { int GetRequired() { object subTarget = fieldInfo.GetValue(target); return((int)GetFieldValue(subTarget, "Required")); } void SetRequired(int flags) { var subTarget = fieldInfo.GetValue(target); SetFieldValue(target: subTarget, fieldName: "Required", value: flags); fieldInfo.SetValue(target, subTarget); } int GetForbidden() { object subTarget = fieldInfo.GetValue(target); return((int)GetFieldValue(subTarget, "Forbidden")); } void SetForbidden(int flags) { var subTarget = fieldInfo.GetValue(target); SetFieldValue(target: subTarget, fieldName: "Forbidden", value: flags); fieldInfo.SetValue(target, subTarget); } Type enumType = fieldInfo.FieldType.GetField("Required").FieldType; enumType = HintExtension.GetMappedEnumWithHints(enumType); var panel0 = BitMaskPanel.Add( roadEditorPanel: instance, container: container, label: prefix + att.name + " Flags Required", enumType: enumType, setHandler: SetRequired, getHandler: GetRequired, hint: hint); panel0.EventPropertyChanged += instance.OnObjectModified; var panel1 = BitMaskPanel.Add( roadEditorPanel: instance, container: container, label: prefix + att.name + " Flags Forbidden", enumType: enumType, setHandler: SetForbidden, getHandler: GetForbidden, hint: hint); panel1.EventPropertyChanged += instance.OnObjectModified; } else if (fieldInfo.FieldType == typeof(NetInfoExtionsion.Range) && fieldInfo.Name.ToLower().Contains("speed")) { var panel = SpeedRangePanel.Add( roadEditorPanel: instance, container: container, label: prefix + att.name, target: target, fieldInfo: fieldInfo); panel.EventPropertyChanged += instance.OnObjectModified; } else { Log.Error($"CreateExtendedComponent: Unhandled field: {fieldInfo} att:{att.name} "); } }
/// <summary> /// Adds new custom fields after a built-in field. /// or modify the name of the built-in fields /// </summary> public static void Postfix(string groupName, FieldInfo field, object target, RoadEditorPanel __instance) { try { if (target is NetLaneProps.Prop prop) { Log.Debug($"{__instance.name}.CreateGenericField.Postfix({groupName},{field},{target})\n" /* + Environment.StackTrace*/); ReplaceLabel(__instance, "Start Flags Required:", "Tail Flags Required:"); ReplaceLabel(__instance, "Start Flags Forbidden:", "Tail Flags Forbidden:"); ReplaceLabel(__instance, "End Flags Required:", "Head Flags Required:"); ReplaceLabel(__instance, "End Flags Forbidden:", "Head Flags Forbidden:"); if (field.Name == nameof(NetLaneProps.Prop.m_endFlagsForbidden)) { Assert(prop.LocateEditProp(out _, out var lane), "could not locate prop"); bool forward = lane.IsGoingForward(); bool backward = lane.IsGoingBackward(); bool unidirectional = forward || backward; if (ModSettings.ARMode) { var metadata = prop.GetOrCreateMetaData(); foreach (var field2 in metadata.GetFieldsWithAttribute <CustomizablePropertyAttribute>()) { CreateExtendedComponent(groupName, field2, metadata, __instance); } } if (!unidirectional) { ButtonPanel.Add( roadEditorPanel: __instance, container: __instance.m_Container, label: "Switch Forward/Backward", null, action: () => { prop.ToggleForwardBackward(); __instance.OnObjectModified(); __instance.Reset(); }); } ButtonPanel.Add( roadEditorPanel: __instance, container: __instance.m_Container, label: "Switch RHT/LHT", HintExtension.GetHintSwichLHT_RHT(unidirectional), action: () => { prop.ToggleRHT_LHT(unidirectional); __instance.OnObjectModified(); __instance.Reset(); }); } } else if (target is NetInfo.Node node) { Log.Debug($"{__instance.name}.CreateGenericField.Postfix({groupName},{field},{target})\n" /* + Environment.StackTrace*/); if (ModSettings.ARMode) { if (field.Name == nameof(NetInfo.Node.m_flagsForbidden)) { var fields = typeof(NetInfoExtionsion.Node).GetFields() .Where(_field => _field.HasAttribute <CustomizablePropertyAttribute>()); var node2 = node.GetOrCreateMetaData(); foreach (var field2 in fields) { CreateExtendedComponent(groupName, field2, node2, __instance); } } } } else if (target is NetInfo.Segment segment) { Log.Debug($"{__instance.name}.CreateGenericField.Postfix({groupName}, {field}, {target})\n" /* + Environment.StackTrace*/); if (ModSettings.ARMode) { var segment2 = segment.GetOrCreateMetaData(); AssertNotNull(segment2, $"{segment}"); var fieldForward = typeof(NetInfoExtionsion.Segment).GetField( nameof(NetInfoExtionsion.Segment.Forward)); if (field.Name == nameof(NetInfo.Segment.m_forwardForbidden)) { CreateExtendedComponent(groupName, fieldForward, segment2, __instance); } else if (field.Name == nameof(NetInfo.Segment.m_backwardForbidden)) { var fields = segment2 .GetFieldsWithAttribute <CustomizablePropertyAttribute>() .Where(_f => _f != fieldForward); int totalCount = typeof(NetInfoExtionsion.Segment) .GetFieldsWithAttribute <CustomizablePropertyAttribute>() .Count(); foreach (var field2 in fields) { CreateExtendedComponent(groupName, field2, segment2, __instance); } } } } else if (target is NetInfo netInfo) { if (ModSettings.ARMode) { // replace "Pavement Width" with Pavement Width Left ReplaceLabel(__instance, "Pavement Width", "Pavement Width Left"); // inject our own field if (field.Name == nameof(NetInfo.m_pavementWidth)) { Log.Debug($"{__instance.name}.CreateGenericField.Postfix({groupName},{field},{target})\n" /* + Environment.StackTrace*/); var net = netInfo.GetOrCreateMetaData(); AssertNotNull(net, $"{netInfo}"); var f = net.GetType().GetField(nameof(net.PavementWidthRight)); __instance.CreateGenericField(groupName, f, net); } } } } catch (Exception e) { Log.Exception(e); } }
public static void AddCrossImportField(this RoadEditorPanel instance) => GetMethod("AddCrossImportField").Invoke(instance, null);
public static void CreateGenericField(this RoadEditorPanel instance, string groupName, FieldInfo field, object target) { GetMethod("CreateGenericField").Invoke(instance, new object[] { groupName, field, target }); }
public static void AddLanePropSelectField(this RoadEditorPanel instance) => GetMethod("AddLanePropSelectField").Invoke(instance, null);
//private void RoadEditorPanel.FitToContainer(UIComponent comp) public static void FitToContainer(this RoadEditorPanel instance, UIComponent comp) => GetMethod("FitToContainer") .Invoke(instance, new object[] { comp });