protected override void OnConstruct() { base.OnConstruct(); _logLines = new string[GetMaxLines()]; _vm = new ScriptVm(); _vm.ShowLineInfo(false); OnRegisterFunctions(_vm); _onDevConsoleId = "DeveloperConsole".GetUiActionGroupId(); _markup = MarkupContainer.CreateMarkup(MarkupSchema); _markup.AttachTheme(Resources.Load <MarkupTheme> (MarkupTheme)); _markup.CreateVisuals(); _markup.GetCanvas().sortingOrder = short.MaxValue; _markup.gameObject.SetActive(false); _logScroll = _markup.GetNamedNode(MarkupScrollViewName).GetComponent <ScrollRect> ().content; _logScroll.pivot = new Vector2(0.5f, 0f); _logText = _markup.GetNamedNode(MarkupLogTextName).GetComponent <Text> (); _logText.horizontalOverflow = HorizontalWrapMode.Overflow; _logText.verticalOverflow = VerticalWrapMode.Overflow; var inputTr = _markup.GetNamedNode(MarkupInputName); var offset = inputTr.offsetMax; offset.x = -CloseButtonWidth; inputTr.offsetMax = offset; _inputField = inputTr.GetComponent <InputField> (); Singleton.Get <UnityEventBus> ().Subscribe <UiInputEndActionData> (OnInputEnd); Singleton.Get <UnityEventBus> ().Subscribe <UiClickActionData> (OnClose); }
/// <summary> /// Create "stack" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "stack"; #endif string attrValue; float amount; var align = OneAxisAlignment.Center; var padding = 0f; var stack = widget.gameObject.AddComponent <StackLayout> (); attrValue = node.GetAttribute(HashedAlign); if (!string.IsNullOrEmpty(attrValue)) { switch (attrValue) { case "start": align = OneAxisAlignment.Start; break; case "end": align = OneAxisAlignment.End; break; } } attrValue = node.GetAttribute(HashedPadding); if (!string.IsNullOrEmpty(attrValue)) { if (float.TryParse(attrValue, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { padding = amount; } } attrValue = node.GetAttribute(HashedVertical); var isVertical = string.CompareOrdinal(attrValue, "true") == 0; attrValue = node.GetAttribute(HashedReverse); var isReverse = string.CompareOrdinal(attrValue, "true") == 0; stack.Padding = padding; stack.ChildAlignment = align; stack.IsVertical = isVertical; stack.IsReverse = isReverse; MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); return(widget); }
/// <summary> /// Create "grid" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "grid"; #endif var grid = widget.gameObject.AddComponent <GridLayoutGroup> (); grid.childAlignment = TextAnchor.MiddleCenter; var flipX = false; var flipY = false; var cellSize = Vector2.zero; var attrValue = node.GetAttribute(HashedFlip); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); flipX = parts.Length > 0 && string.CompareOrdinal(parts[0], "true") == 0; flipY = parts.Length > 1 && string.CompareOrdinal(parts[1], "true") == 0; } float amount; attrValue = node.GetAttribute(HashedCellSize); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); if (parts.Length > 0 && !string.IsNullOrEmpty(parts[0])) { if (float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { cellSize.x = amount; } } if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1])) { if (float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { cellSize.y = amount; } } } grid.cellSize = cellSize; grid.startCorner = (GridLayoutGroup.Corner)((flipX ? 1 : 0) | (flipY ? 2 : 0)); MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); return(widget); }
/// <summary> /// Create "align" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "align"; #endif var rt = widget.GetComponent <RectTransform> (); var deltaSize = Vector2.zero; var anchorMin = Vector2.zero; var anchorMax = Vector2.one; var attrValue = node.GetAttribute(HashedSide); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); for (var i = 0; i < parts.Length; i++) { switch (parts[i]) { case "left": anchorMax.x = 0f; deltaSize.x = 1f; break; case "right": anchorMin.x = 1f; deltaSize.x = 1f; break; case "top": anchorMin.y = 1f; deltaSize.y = 1f; break; case "bottom": anchorMax.y = 0f; deltaSize.y = 1f; break; } } } rt.anchorMin = anchorMin; rt.anchorMax = anchorMax; rt.sizeDelta = deltaSize; MarkupUtils.SetHidden(widget, node); return(widget); }
/// <summary> /// Create "fixedTable" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "fixedTable"; #endif var table = widget.gameObject.AddComponent <FixedTableLayout> (); var itemsInRow = 1; var cellSize = Vector2.zero; var attrValue = node.GetAttribute(HashedItemsInRow); if (!string.IsNullOrEmpty(attrValue)) { int.TryParse(attrValue, out itemsInRow); } float amount; attrValue = node.GetAttribute(HashedCellSize); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); if (parts.Length > 0 && !string.IsNullOrEmpty(parts[0])) { if (float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { cellSize.x = amount; } } if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1])) { if (float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { cellSize.y = amount; } } } table.ItemsInRow = itemsInRow; table.CellSize = cellSize; MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); return(widget); }
/// <summary> /// Create "box" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "box"; #endif MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); if (MarkupUtils.ValidateInteractive(widget, node, container.DragTreshold)) { widget.gameObject.AddComponent <NonVisualWidget> (); } return(widget); }
/// <summary> /// Create "toggleGroup" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "toggleGroup"; #endif var checkGroup = widget.gameObject.AddComponent <ToggleGroup> (); var attrValue = node.GetAttribute(HashedEmptyCheck); if (string.CompareOrdinal(attrValue, "true") == 0) { checkGroup.allowSwitchOff = true; } MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); return(widget); }
/// <summary> /// Create "scrollView" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "scrollView"; #endif float amount; string attrValue; Scrollbar horScroll = null; Scrollbar verScroll = null; var anchorMin = Vector2.zero; var anchorMax = Vector2.one; var offsetMin = Vector3.zero; var offsetMax = Vector3.zero; var needHorScroll = true; var needVerScroll = true; var theme = MarkupUtils.GetTheme(node, container); var scrollView = widget.gameObject.AddComponent <ScrollRect> (); // viewport. var viewport = MarkupUtils.CreateUiObject(ViewportName, widget); viewport.gameObject.AddComponent <RectMask2D> (); viewport.gameObject.AddComponent <NonVisualWidget> ().raycastTarget = false; viewport.anchorMin = Vector2.zero; viewport.anchorMax = Vector2.one; viewport.sizeDelta = Vector2.zero; viewport.pivot = Vector2.up; // content. var content = MarkupUtils.CreateUiObject(ContentName, viewport); attrValue = node.GetAttribute(HashedContentSize); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); if (parts.Length > 0 && !string.IsNullOrEmpty(parts[0])) { if (float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { amount *= 0.5f; offsetMin.x = -amount; offsetMax.x = amount; anchorMin.x = 0.5f; anchorMax.x = 0.5f; } } if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1])) { if (float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { amount *= 0.5f; offsetMin.y = -amount; offsetMax.y = amount; anchorMin.y = 0.5f; anchorMax.y = 0.5f; } } } content.anchorMin = anchorMin; content.anchorMax = anchorMax; content.offsetMin = offsetMin; content.offsetMax = offsetMax; attrValue = node.GetAttribute(HashedClamp); if (string.CompareOrdinal(attrValue, "true") == 0) { scrollView.movementType = ScrollRect.MovementType.Clamped; } attrValue = node.GetAttribute(HashedDrag); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); if (parts.Length > 0 && string.CompareOrdinal(parts[0], "false") == 0) { scrollView.horizontal = false; } if (parts.Length > 1 && string.CompareOrdinal(parts[1], "false") == 0) { scrollView.vertical = false; } } attrValue = node.GetAttribute(HashedBar); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); if (parts.Length > 0 && string.CompareOrdinal(parts[0], "false") == 0) { needHorScroll = false; } if (parts.Length > 1 && string.CompareOrdinal(parts[1], "false") == 0) { needVerScroll = false; } } if (needHorScroll) { horScroll = CreateScrollbar(widget, theme, true); MarkupUtils.SetNav(horScroll, node, container.UseNavigation); } if (needVerScroll) { verScroll = CreateScrollbar(widget, theme, false); MarkupUtils.SetNav(verScroll, node, container.UseNavigation); } attrValue = node.GetAttribute(HashedOnChange); if (!string.IsNullOrEmpty(attrValue)) { widget.gameObject.AddComponent <NonVisualWidget> (); widget.gameObject.AddComponent <UiScrollViewAction> ().SetGroup(attrValue); } scrollView.content = content; scrollView.viewport = viewport; scrollView.horizontalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport; scrollView.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport; scrollView.horizontalScrollbar = horScroll; scrollView.verticalScrollbar = verScroll; scrollView.decelerationRate = 0.01f; MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); scrollView.normalizedPosition = Vector2.up; return(content); }
/// <summary> /// Create "slider" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "slider"; #endif var slider = widget.gameObject.AddComponent <Slider> (); var theme = MarkupUtils.GetTheme(node, container); Image img; RectTransform rt; var direction = Slider.Direction.LeftToRight; var minValue = 0f; var maxValue = 1f; var useInts = false; var dataValue = 0f; var isInteractive = false; // background. rt = MarkupUtils.CreateUiObject(BackgroundImageName, widget); img = rt.gameObject.AddComponent <Image> (); img.sprite = theme.GetSliderSprite(MarkupTheme.SliderState.Background); img.color = theme.GetSliderColor(MarkupTheme.SliderState.Background); img.type = Image.Type.Sliced; rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.sizeDelta = Vector2.zero; // foreground. rt = MarkupUtils.CreateUiObject(ForegroundImageName, widget); img = rt.gameObject.AddComponent <Image> (); img.sprite = theme.GetSliderSprite(MarkupTheme.SliderState.Foreground); img.color = theme.GetSliderColor(MarkupTheme.SliderState.Foreground); img.type = Image.Type.Sliced; img.raycastTarget = false; rt.sizeDelta = Vector2.zero; slider.fillRect = rt; string attrValue; attrValue = node.GetAttribute(HashedHandle); var useHandle = string.CompareOrdinal(attrValue, "true") == 0; if (useHandle) { var handle = MarkupUtils.CreateUiObject(null, widget); slider.handleRect = handle; rt = MarkupUtils.CreateUiObject(HandleImageName, handle); img = rt.gameObject.AddComponent <Image> (); img.raycastTarget = false; img.sprite = theme.GetSliderSprite(MarkupTheme.SliderState.Handle); img.color = theme.GetSliderColor(MarkupTheme.SliderState.Handle); img.type = Image.Type.Sliced; img.SetNativeSize(); handle.sizeDelta = img.rectTransform.sizeDelta; } attrValue = node.GetAttribute(HashedRtl); if (string.CompareOrdinal(attrValue, "true") == 0) { direction = Slider.Direction.RightToLeft; } float amount; attrValue = node.GetAttribute(HashedRange); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); if (parts.Length > 0 && !string.IsNullOrEmpty(parts[0])) { if (float.TryParse(parts[0], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { minValue = amount; } } if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1])) { if (float.TryParse(parts[1], NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { maxValue = amount; } } if (parts.Length > 2 && string.CompareOrdinal(parts[2], "true") == 0) { useInts = true; } } attrValue = node.GetAttribute(HashedValue); if (!string.IsNullOrEmpty(attrValue)) { if (float.TryParse(attrValue, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out amount)) { dataValue = amount; } } attrValue = node.GetAttribute(HashedOnChange); if (!string.IsNullOrEmpty(attrValue)) { widget.gameObject.AddComponent <UiSliderAction> ().SetGroup(attrValue); isInteractive = true; } slider.minValue = minValue; slider.maxValue = maxValue; slider.wholeNumbers = useInts; slider.value = dataValue; slider.direction = direction; slider.transition = Selectable.Transition.None; MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); MarkupUtils.SetNav(slider, node, container.UseNavigation); slider.interactable = useHandle && isInteractive; return(widget); }
/// <summary> /// Create "button" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "button"; #endif var btn = widget.gameObject.AddComponent <Button> (); var img = widget.gameObject.AddComponent <Image> (); string attrValue; var transition = Selectable.Transition.ColorTint; attrValue = node.GetAttribute(HashedBlend); switch (attrValue) { case "sprites": transition = Selectable.Transition.SpriteSwap; break; case "none": transition = Selectable.Transition.None; break; } var theme = MarkupUtils.GetTheme(node, container); switch (transition) { case Selectable.Transition.ColorTint: var colors = btn.colors; colors.normalColor = theme.GetButtonColor(MarkupTheme.ButtonState.Normal); colors.pressedColor = theme.GetButtonColor(MarkupTheme.ButtonState.Pressed); colors.highlightedColor = theme.GetButtonColor(MarkupTheme.ButtonState.Highlighted); colors.disabledColor = theme.GetButtonColor(MarkupTheme.ButtonState.Disabled); btn.colors = colors; break; case Selectable.Transition.SpriteSwap: var sprites = btn.spriteState; sprites.pressedSprite = theme.GetButtonSprite(MarkupTheme.ButtonState.Pressed); sprites.highlightedSprite = theme.GetButtonSprite(MarkupTheme.ButtonState.Highlighted); sprites.disabledSprite = theme.GetButtonSprite(MarkupTheme.ButtonState.Disabled); btn.spriteState = sprites; break; } img.sprite = theme.GetButtonSprite(MarkupTheme.ButtonState.Normal); img.type = Image.Type.Sliced; btn.targetGraphic = img; btn.transition = transition; MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); MarkupUtils.SetNav(btn, node, container.UseNavigation); attrValue = node.GetAttribute(HashedDisabled); var disabled = string.CompareOrdinal(attrValue, "true") == 0; btn.interactable = !disabled && MarkupUtils.ValidateInteractive(widget, node, container.DragTreshold); return(widget); }
/// <summary> /// Create "ui" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "ui"; #endif var go = widget.gameObject; var canvas = go.AddComponent <Canvas> (); canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.pixelPerfect = false; var pixelSize = 1f; var dragTreshold = 5; var scaler = go.AddComponent <CanvasScaler> (); var attrValue = node.GetAttribute(HashedBase); if (attrValue != null) { var refWidth = 1024; var refHeight = 768; var refBalance = 1f; try { var parts = MarkupUtils.SplitAttrValue(attrValue); var w = int.Parse(parts[0]); var h = int.Parse(parts[1]); var b = Mathf.Clamp01(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)); refWidth = w; refHeight = h; refBalance = b; } catch { } scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; scaler.referenceResolution = new Vector2(refWidth, refHeight); scaler.matchWidthOrHeight = refBalance; if (Application.isPlaying) { pixelSize = Mathf.Lerp(Screen.width / (float)refWidth, Screen.height / (float)refHeight, refBalance); } else { pixelSize = 1f; } } attrValue = node.GetAttribute(HashedDragTreshold); if (attrValue != null) { if (int.TryParse(attrValue, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out dragTreshold)) { dragTreshold = Mathf.Max(1, dragTreshold); } } container.PixelSize = pixelSize; container.DragTreshold = dragTreshold * pixelSize; go.AddComponent <GraphicRaycaster> (); if (Application.isPlaying) { var es = Object.FindObjectOfType <EventSystem> (); if ((object)es == null) { es = new GameObject("EventSystem").AddComponent <EventSystem> (); es.gameObject.AddComponent <StandaloneInputModule> (); } } return(widget); }
/// <summary> /// Create "image" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "image"; #endif Image img = null; RawImage tex = null; string attrValue; var useImg = true; var ignoreSize = false; var fillCenter = true; attrValue = node.GetAttribute(HashedRaw); if (string.CompareOrdinal(attrValue, "true") == 0) { useImg = false; tex = widget.gameObject.AddComponent <RawImage> (); } else { img = widget.gameObject.AddComponent <Image> (); img.type = Image.Type.Sliced; } attrValue = node.GetAttribute(HashedPath); if (!string.IsNullOrEmpty(attrValue)) { if (useImg) { // Image. var parts = MarkupUtils.SplitAttrValue(attrValue); if (parts.Length == 2) { var atlas = container.GetAtlas(parts[0]); if ((object)atlas != null) { img.sprite = atlas.Get(parts[1]); } } } else { // RawImage. tex.texture = Resources.Load <Texture2D> (attrValue); } } if (useImg) { attrValue = node.GetAttribute(HashedNativeSize); ignoreSize = (object)img.sprite != null && string.CompareOrdinal(attrValue, "true") == 0; } if (useImg && ignoreSize) { img.SetNativeSize(); } else { MarkupUtils.SetSize(widget, node); } attrValue = node.GetAttribute(HashedMask); if (string.CompareOrdinal(attrValue, "true") == 0) { widget.gameObject.AddComponent <Mask> (); } if (useImg) { attrValue = node.GetAttribute(HashedFillCenter); if (string.CompareOrdinal(attrValue, "false") == 0) { fillCenter = false; } img.fillCenter = fillCenter; } if (useImg && !MarkupUtils.SetColor(img, node)) { img.color = Color.white; } MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); var isInteractive = MarkupUtils.ValidateInteractive(widget, node, container.DragTreshold); if (useImg) { img.raycastTarget = isInteractive; } else { tex.raycastTarget = isInteractive; } return(widget); }
/// <summary> /// Takes the source HTML and makes necessary modifications to keep the source formatting as if it were to be /// pasted into the destination range. /// </summary> /// <param name="sourceRange">The range containing the HTML that is being copied.</param> /// <param name="destinationRange">The range that the source HTML will be copied to.</param> /// <returns>A serialized string of the source HTML with necessary modifications to keep the source formatting /// or null if unsuccessful.</returns> private string KeepSourceFormatting(MarkupRange sourceRange, MarkupRange destinationRange) { Debug.Assert(sourceRange.Start.Container.GetOwningDoc() == destinationRange.Start.Container.GetOwningDoc(), "Ranges must share an owning document!"); // We will temporarily add comments to the destination document to mark the destinationRange. IHTMLElement startComment = null; IHTMLElement endComment = null; try { // This is our true destination document. IHTMLDocument2 destinationDocument = destinationRange.Start.Container.Document; MshtmlMarkupServices destinationMarkupServices = new MshtmlMarkupServices((IMarkupServicesRaw)destinationDocument); // However, we'll use a temp destination because we don't want to paste anything into the real // document yet as it could fail, it would fire events, images would start loading, etc. MarkupContainer temporaryDestinationContainer = destinationMarkupServices.CreateMarkupContainer(); MarkupPointer temporaryDestinationPointer = destinationMarkupServices.CreateMarkupPointer(); temporaryDestinationPointer.MoveToContainer(temporaryDestinationContainer, true); // We add in comments to the destination document so that when we copy this range over to the fake // destination we'll be able to find the range again. destinationRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; destinationRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; string startMarker = string.Format(CultureInfo.InvariantCulture, "<!--{0}-->", Guid.NewGuid()); destinationMarkupServices.InsertHtml(startMarker, destinationRange.Start); startComment = destinationRange.Start.Right(false).Element; string endMarker = string.Format(CultureInfo.InvariantCulture, "<!--{0}-->", Guid.NewGuid()); destinationMarkupServices.InsertHtml(endMarker, destinationRange.End); endComment = destinationRange.End.Left(false).Element; try { // Copy over the entire destination document into the fake destination document. MarkupRange destinationAll = SelectAll(destinationDocument); destinationMarkupServices.Copy(destinationAll.Start, destinationAll.End, temporaryDestinationPointer); // Find the original destination range in this copy. MarkupRange temporaryDestinationRange = FindMarkedFragment(temporaryDestinationContainer.Document, startMarker, endMarker); if (temporaryDestinationRange != null) { // Do the work to keep the source formatting. MarkupRange inlinedRange = new KeepSourceFormatting(sourceRange, temporaryDestinationRange).Execute(); if (inlinedRange != null) { return(inlinedRange.HtmlText); } } } finally { // WinLive 249077: Clear the temporary destination container, otherwise behaviors may // inadvertently attach to elements in the MarkupContainer. temporaryDestinationContainer.Document.body.innerHTML = String.Empty; } } catch (Exception e) { // I really dont want some funky html on the clipboard that causes a problem with this code // to prevent a paste from going through. Trace.Fail("Failed to get inline css for selection: " + e); } finally { Debug.Assert(startComment is IHTMLCommentElement, "Didn't find start comment or it wasn't created."); if (startComment is IHTMLCommentElement) { HTMLElementHelper.RemoveElement(startComment); } Debug.Assert(endComment is IHTMLCommentElement, "Didn't find end comment or it wasn't created."); if (endComment is IHTMLCommentElement) { HTMLElementHelper.RemoveElement(endComment); } } return(null); }
/// <summary> /// Create "toggle" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "toggle"; #endif var tr = widget.transform; Image img; RectTransform rt; Vector2 size; string attrValue; var toggle = widget.gameObject.AddComponent <Toggle> (); var theme = MarkupUtils.GetTheme(node, container); var isInteractive = false; // background. rt = MarkupUtils.CreateUiObject(BackgroundImageName, tr); img = rt.gameObject.AddComponent <Image> (); img.sprite = theme.GetToggleSprite(MarkupTheme.ToggleState.Background); img.type = Image.Type.Sliced; img.raycastTarget = false; size = theme.GetToggleSize(MarkupTheme.ToggleState.Background); rt.anchorMin = new Vector2(0f, 0.5f); rt.anchorMax = new Vector2(0f, 0.5f); rt.offsetMin = new Vector2(0f, -size.y * 0.5f); rt.offsetMax = new Vector2(size.x, size.y * 0.5f); toggle.targetGraphic = img; // foreground. rt = MarkupUtils.CreateUiObject(ForegroundImageName, rt); img = rt.gameObject.AddComponent <Image> (); rt.anchorMin = new Vector2(0.5f, 0.5f); rt.anchorMax = new Vector2(0.5f, 0.5f); rt.sizeDelta = theme.GetToggleSize(MarkupTheme.ToggleState.Foreground); img.sprite = theme.GetToggleSprite(MarkupTheme.ToggleState.Foreground); img.type = Image.Type.Sliced; img.raycastTarget = false; toggle.graphic = img; // content. rt = MarkupUtils.CreateUiObject(ContentName, tr); rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = Vector2.right * size.x; rt.offsetMax = Vector2.zero; attrValue = node.GetAttribute(HashedGroup); if (!string.IsNullOrEmpty(attrValue)) { var groupGo = container.GetNamedNode(attrValue); if ((object)groupGo != null) { toggle.group = groupGo.GetComponent <ToggleGroup> (); } } attrValue = node.GetAttribute(HashedCheck); if (string.CompareOrdinal(attrValue, "true") == 0) { toggle.isOn = true; } attrValue = node.GetAttribute(HashedOnChange); if (!string.IsNullOrEmpty(attrValue)) { widget.gameObject.AddComponent <NonVisualWidget> (); widget.gameObject.AddComponent <UiToggleAction> ().SetGroup(attrValue); isInteractive = true; } toggle.transition = Selectable.Transition.None; toggle.interactable = isInteractive; MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); MarkupUtils.SetNav(toggle, node, container.UseNavigation); return(rt); }
/// <summary> /// Create "input" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "input"; #endif var input = widget.gameObject.AddComponent <InputField> (); string attrValue; string font = null; var align = TextAnchor.MiddleLeft; var style = FontStyle.Normal; var size = 24; var isInteractive = false; var theme = MarkupUtils.GetTheme(node, container); var img = widget.gameObject.AddComponent <Image> (); img.type = Image.Type.Sliced; img.sprite = theme.GetInputSprite(); img.color = theme.GetInputColor(MarkupTheme.InputState.Background); var ph = MarkupUtils.CreateUiObject(null, widget); var phText = ph.gameObject.AddComponent <Text> (); phText.fontStyle = FontStyle.Italic; var txt = MarkupUtils.CreateUiObject(null, widget); var inText = txt.gameObject.AddComponent <Text> (); inText.supportRichText = false; attrValue = node.GetAttribute(HashedFontName); if (!string.IsNullOrEmpty(attrValue)) { font = attrValue; } attrValue = node.GetAttribute(HashedFontSize); if (!string.IsNullOrEmpty(attrValue)) { int.TryParse(attrValue, out size); } attrValue = node.GetAttribute(HashedFontStyle); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); for (var i = 0; i < parts.Length; i++) { switch (parts[i]) { case "bold": style |= FontStyle.Bold; break; case "italic": style |= FontStyle.Italic; break; } } } attrValue = node.GetAttribute(HashedAlign); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); var alignHor = 1; var alignVer = 3; for (var i = 0; i < parts.Length; i++) { switch (parts[i]) { case "left": alignHor = 0; break; case "right": alignHor = 2; break; case "top": alignVer = 0; break; case "bottom": alignVer = 6; break; } } align = (TextAnchor)(alignHor + alignVer); } attrValue = node.GetAttribute(HashedLocalize); if (!string.IsNullOrEmpty(attrValue)) { phText.gameObject.AddComponent <TextLocalization> ().SetToken(attrValue); } else { phText.text = node.Value; } var margin = theme.GetInputMargin(); var marginMin = new Vector2(margin, margin); var marginMax = -marginMin; ph.anchorMin = Vector2.zero; ph.anchorMax = Vector2.one; ph.offsetMin = marginMin; ph.offsetMax = marginMax; txt.anchorMin = Vector2.zero; txt.anchorMax = Vector2.one; txt.offsetMin = marginMin; txt.offsetMax = marginMax; phText.raycastTarget = false; inText.raycastTarget = false; phText.alignment = align; inText.alignment = align; phText.font = container.GetFont(font); inText.font = phText.font; phText.color = theme.GetInputColor(MarkupTheme.InputState.Placeholder); if (!MarkupUtils.SetColor(inText, node)) { inText.color = Color.black; } phText.fontStyle = theme.GetInputPlaceholderStyle(); inText.fontStyle = style; phText.fontSize = size; inText.fontSize = size; input.targetGraphic = img; input.transition = Selectable.Transition.None; input.placeholder = phText; input.textComponent = inText; input.selectionColor = theme.GetInputColor(MarkupTheme.InputState.Selection); MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); MarkupUtils.SetNav(input, node, container.UseNavigation); attrValue = node.GetAttribute(HashedOnChange); if (!string.IsNullOrEmpty(attrValue)) { widget.gameObject.AddComponent <UiInputAction> ().SetGroup(attrValue); isInteractive = true; } input.interactable = isInteractive; return(widget); }
/// <summary> /// Grabs HTML copied in the clipboard and pastes it into the document (pulls in a copy of embedded content too) /// </summary> protected override bool DoInsertData(DataAction action, MarkupPointer begin, MarkupPointer end) { using (new WaitCursor()) { try { string baseUrl = UrlHelper.GetBasePathUrl(DataMeister.HTMLData.SourceURL); string html = DataMeister.HTMLData.HTMLSelection; //Check to see if the selection has an incomplete unordered list var finder = new IncompleteListFinder(html); finder.Parse(); if ((!EditorContext.CleanHtmlOnPaste) || finder.HasIncompleteList) { using (IUndoUnit undoUnit = EditorContext.CreateInvisibleUndoUnit()) { // Create a new MarkupContainer off of EditorContext's document that contains the source HTML // with comments marking the start and end selection. MarkupContainer sourceContainer = EditorContext.MarkupServices.ParseString(DataMeister.HTMLData.HTMLWithMarkers); // MSHTML's ParseString implementation clears all the attributes on the <body> element, so we // have to manually add them back in. CopyBodyAttributes(DataMeister.HTMLData.HTMLWithMarkers, sourceContainer.Document.body); MarkupRange sourceRange = FindMarkedFragment(sourceContainer.Document, HTMLDataObject.START_FRAGMENT_MARKER, HTMLDataObject.END_FRAGMENT_MARKER); MshtmlMarkupServices sourceContainerMarkupServices = new MshtmlMarkupServices((IMarkupServicesRaw)sourceContainer.Document); // Some applications may not add the correct fragment markers (e.g. copying from Fiddler from // the Web Sessions view). We'll just select the entire <body> of the clipboard in this case. if (sourceRange == null) { sourceRange = sourceContainerMarkupServices.CreateMarkupRange(sourceContainer.Document.body, false); } else { // Make sure that we don't try to copy just parts of a table/list. We need to include the // parent table/list. if (!EditorContext.CleanHtmlOnPaste) { ExpandToIncludeTables(sourceRange, sourceContainerMarkupServices); } ExpandToIncludeLists(sourceRange, sourceContainerMarkupServices); } if (sourceRange != null) { if (!EditorContext.CleanHtmlOnPaste) { // WinLive 273280: Alignment on a table acts like a float, which can throw off the layout of the rest of // the document. If there is nothing before or after the table, then we can safely remove the alignment. RemoveAlignmentIfSingleTable(sourceRange); // Serialize the source HTML to a string while keeping the source formatting. MarkupRange destinationRange = EditorContext.MarkupServices.CreateMarkupRange(begin.Clone(), end.Clone()); html = KeepSourceFormatting(sourceRange, destinationRange); } else { html = sourceRange.HtmlText; } } undoUnit.Commit(); } Trace.Assert(html != null, "Inline source CSS failed!"); } if (html == null) { html = DataMeister.HTMLData.HTMLSelection; } if (IsPasteFromSharedCanvas(DataMeister)) { if (action == DataAction.Copy) { // WinLive 96840 - Copying and pasting images within shared canvas should persist source // decorator settings. "wlCopySrcUrl" is inserted while copy/pasting within canvas. html = EditorContext.FixImageReferences(ImageCopyFixupHelper.FixupSourceUrlForCopy(html), DataMeister.HTMLData.SourceURL); } } else { html = EditorContext.FixImageReferences(html, DataMeister.HTMLData.SourceURL); HtmlCleanupRule cleanupRule = HtmlCleanupRule.Normal; if (IsOfficeHtml(DataMeister.HTMLData)) { cleanupRule = HtmlCleanupRule.PreserveTables; } // In Mail, we want to preserve the style of the html that is on the clipboard // Whereas in Writer we by default want to remove formatting so it looks like your blog theme if (EditorContext.CleanHtmlOnPaste) { // optionally cleanup the html html = EditorContext.HtmlGenerationService.CleanupHtml(html, baseUrl, cleanupRule); } else { html = HtmlCleaner.StripNamespacedTagsAndCommentsAndMarkupDirectives(html); } // standard fixups html = EditorContext.HtmlGenerationService.GenerateHtmlFromHtmlFragment(html, baseUrl); } // insert the content if (EditorContext.MarshalHtmlSupported) { EditorContext.InsertHtml(begin, end, html, DataMeister.HTMLData.SourceURL); } else if (EditorContext.MarshalTextSupported) { // This is called only in the case that we're attempting to marshal HTML, but only // text is supported. In this case, we should down convert to text and provide that. html = HTMLDocumentHelper.HTMLToPlainText(html); EditorContext.InsertHtml(begin, end, html, DataMeister.HTMLData.SourceURL); } else { Debug.Assert(false, "Html being inserted when text or html isn't supported."); } // Now select what was just inserted EditorContext.MarkupServices.CreateMarkupRange(begin, end).ToTextRange().select(); //place the caret at the end of the inserted content //EditorContext.MoveCaretToMarkupPointer(end, true); return(true); } catch (Exception e) { //bugfix 1696, put exceptions into the trace log. Trace.Fail("Exception while inserting HTML: " + e.Message, e.StackTrace); return(false); } } }
/// <summary> /// Create "text" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "text"; #endif var txt = widget.gameObject.AddComponent <Text> (); string attrValue; string font = null; var align = TextAnchor.MiddleCenter; var style = FontStyle.Normal; var size = 24; attrValue = node.GetAttribute(HashedFontName); if (!string.IsNullOrEmpty(attrValue)) { font = attrValue; } attrValue = node.GetAttribute(HashedFontSize); if (!string.IsNullOrEmpty(attrValue)) { int.TryParse(attrValue, out size); } attrValue = node.GetAttribute(HashedFontStyle); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); for (var i = 0; i < parts.Length; i++) { switch (parts[i]) { case "bold": style |= FontStyle.Bold; break; case "italic": style |= FontStyle.Italic; break; } } } attrValue = node.GetAttribute(HashedAlign); if (!string.IsNullOrEmpty(attrValue)) { var parts = MarkupUtils.SplitAttrValue(attrValue); var alignHor = 1; var alignVer = 3; for (var i = 0; i < parts.Length; i++) { switch (parts[i]) { case "left": alignHor = 0; break; case "right": alignHor = 2; break; case "top": alignVer = 0; break; case "bottom": alignVer = 6; break; } } align = (TextAnchor)(alignHor + alignVer); } attrValue = node.GetAttribute(HashedLocalize); if (!string.IsNullOrEmpty(attrValue)) { widget.gameObject.AddComponent <TextLocalization> ().SetToken(attrValue); } else { txt.text = node.Value; } txt.alignment = align; txt.font = container.GetFont(font); txt.fontStyle = style; txt.fontSize = size; if (!MarkupUtils.SetColor(txt, node)) { txt.color = Color.black; } MarkupUtils.SetSize(widget, node); MarkupUtils.SetRotation(widget, node); MarkupUtils.SetOffset(widget, node); MarkupUtils.SetHidden(widget, node); txt.raycastTarget = MarkupUtils.ValidateInteractive(widget, node, container.DragTreshold); return(widget); }
/// <summary> /// Create "ui" node. If children supported - GameObject container for them should be returned. /// </summary> /// <param name="widget">Ui widget.</param> /// <param name="node">Xml node.</param> /// <param name="container">Markup container.</param> public static RectTransform Create(RectTransform widget, XmlNode node, MarkupContainer container) { #if UNITY_EDITOR widget.name = "ui"; #endif var go = widget.gameObject; var canvas = go.AddComponent <Canvas> (); Camera uiCamera = null; if (Application.isPlaying) { canvas.renderMode = RenderMode.ScreenSpaceCamera; uiCamera = MarkupUtils.GetUiCamera(); canvas.worldCamera = uiCamera; } else { canvas.renderMode = RenderMode.ScreenSpaceOverlay; } canvas.planeDistance = 0f; canvas.pixelPerfect = false; var pixelSize = 1f; var dragTreshold = 5; var scaler = go.AddComponent <CanvasScaler> (); var attrValue = node.GetAttribute(HashedBase); if (attrValue != null) { var refWidth = 1024; var refHeight = 768; var refBalance = 1f; try { var parts = MarkupUtils.SplitAttrValue(attrValue); var w = int.Parse(parts[0]); var h = int.Parse(parts[1]); var b = Mathf.Clamp01(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)); refWidth = w; refHeight = h; refBalance = b; } catch { } scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; scaler.referenceResolution = new Vector2(refWidth, refHeight); scaler.matchWidthOrHeight = refBalance; if (Application.isPlaying) { if (refBalance < 1f) { Debug.LogWarning("Only height-based balance supported"); } uiCamera.orthographicSize = refHeight * 0.5f; pixelSize = MathFast.Lerp(Screen.width / (float)refWidth, Screen.height / (float)refHeight, refBalance); } else { pixelSize = 1f; } } attrValue = node.GetAttribute(HashedDragTreshold); if (attrValue != null) { if (int.TryParse(attrValue, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out dragTreshold)) { dragTreshold = Mathf.Max(1, dragTreshold); } } attrValue = node.GetAttribute(MarkupUtils.HashedNav); var disableNav = string.CompareOrdinal(attrValue, "false") == 0; container.PixelSize = pixelSize; container.DragTreshold = dragTreshold * pixelSize; container.UseNavigation = !disableNav; go.AddComponent <GraphicRaycaster> (); if (Application.isPlaying) { var es = Object.FindObjectOfType <EventSystem> (); if ((object)es == null) { es = new GameObject("EventSystem").AddComponent <EventSystem> (); es.gameObject.AddComponent <StandaloneInputModule> (); } } return(widget); }