From d07e14add74e017b52ab2371efeea1aa4ea10ced Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 8 May 2021 23:15:13 +0800 Subject: +init --- .../UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs | 307 +++ .../UI/Core/CanvasUpdateRegistry.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Culling.meta | 10 + .../UI/Core/Culling/ClipperRegistry.cs | 50 + .../UI/Core/Culling/ClipperRegistry.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Culling/Clipping.cs | 44 + .../UI/Core/Culling/Clipping.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Culling/IClipRegion.cs | 16 + .../UI/Core/Culling/IClipRegion.cs.meta | 13 + .../UI/Core/Culling/RectangularVertexClipper.cs | 21 + .../Core/Culling/RectangularVertexClipper.cs.meta | 13 + .../uGUI-2017.1/UnityEngine.UI/UI/Core/Font.meta | 8 + .../UnityEngine.UI/UI/Core/Font/FontData.cs | 158 ++ .../UnityEngine.UI/UI/Core/Font/FontData.cs.meta | 13 + .../UI/Core/Font/FontUpdateTracker.cs | 71 + .../UI/Core/Font/FontUpdateTracker.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Font/Text.cs | 576 +++++ .../UnityEngine.UI/UI/Core/Font/Text.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Graphics.meta | 8 + .../UnityEngine.UI/UI/Core/Graphics/Graphic.cs | 669 ++++++ .../UI/Core/Graphics/Graphic.cs.meta | 11 + .../UI/Core/Graphics/GraphicRaycaster.cs | 290 +++ .../UI/Core/Graphics/GraphicRaycaster.cs.meta | 11 + .../UI/Core/Graphics/GraphicRebuildTracker.cs | 38 + .../UI/Core/Graphics/GraphicRebuildTracker.cs.meta | 11 + .../UI/Core/Graphics/GraphicRegistry.cs | 78 + .../UI/Core/Graphics/GraphicRegistry.cs.meta | 11 + .../UI/Core/Graphics/IGraphicEnabledDisabled.cs | 10 + .../Core/Graphics/IGraphicEnabledDisabled.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Graphics/Image.cs | 1171 +++++++++ .../UnityEngine.UI/UI/Core/Graphics/Image.cs.meta | 11 + .../UI/Core/Graphics/MaskableGraphic.cs | 235 ++ .../UI/Core/Graphics/MaskableGraphic.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Graphics/RawImage.cs | 120 + .../UI/Core/Graphics/RawImage.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Graphics/SpriteState.cs | 33 + .../UI/Core/Graphics/SpriteState.cs.meta | 11 + .../uGUI-2017.1/UnityEngine.UI/UI/Core/Layout.meta | 10 + .../UI/Core/Layout/AspectRatioFitter.cs | 145 ++ .../UI/Core/Layout/AspectRatioFitter.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs | 241 ++ .../UI/Core/Layout/CanvasScaler.cs.meta | 13 + .../UI/Core/Layout/ContentSizeFitter.cs | 103 + .../UI/Core/Layout/ContentSizeFitter.cs.meta | 13 + .../UI/Core/Layout/GridLayoutGroup.cs | 207 ++ .../UI/Core/Layout/GridLayoutGroup.cs.meta | 13 + .../UI/Core/Layout/HorizontalLayoutGroup.cs | 30 + .../UI/Core/Layout/HorizontalLayoutGroup.cs.meta | 13 + .../Core/Layout/HorizontalOrVerticalLayoutGroup.cs | 179 ++ .../Layout/HorizontalOrVerticalLayoutGroup.cs.meta | 13 + .../UI/Core/Layout/ILayoutElement.cs | 50 + .../UI/Core/Layout/ILayoutElement.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Layout/LayoutElement.cs | 78 + .../UI/Core/Layout/LayoutElement.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs | 237 ++ .../UI/Core/Layout/LayoutGroup.cs.meta | 13 + .../UI/Core/Layout/LayoutRebuilder.cs | 233 ++ .../UI/Core/Layout/LayoutRebuilder.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs | 112 + .../UI/Core/Layout/LayoutUtility.cs.meta | 13 + .../UI/Core/Layout/VerticalLayoutGroup.cs | 30 + .../UI/Core/Layout/VerticalLayoutGroup.cs.meta | 13 + .../uGUI-2017.1/UnityEngine.UI/UI/Core/Mask.meta | 8 + .../UnityEngine.UI/UI/Core/Mask/IMask.cs | 11 + .../UnityEngine.UI/UI/Core/Mask/IMask.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Mask/IMaskable.cs | 9 + .../UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Mask/Mask.cs | 203 ++ .../UnityEngine.UI/UI/Core/Mask/Mask.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs | 187 ++ .../UI/Core/Mask/MaskUtilities.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Mask/RectMask2D.cs | 198 ++ .../UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs | 169 ++ .../UI/Core/Mask/StencilMaterial.cs.meta | 11 + .../UnityEngine.UI/UI/Core/MaterialModifiers.meta | 10 + .../UI/Core/MaterialModifiers/IMaterialModifier.cs | 7 + .../MaterialModifiers/IMaterialModifier.cs.meta | 13 + Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs | 44 + .../UnityEngine.UI/UI/Core/Misc.cs.meta | 13 + .../UI/Core/SpecializedCollections.meta | 10 + .../UI/Core/SpecializedCollections/IndexedSet.cs | 152 ++ .../Core/SpecializedCollections/IndexedSet.cs.meta | 13 + .../UnityEngine.UI/UI/Core/UIControls.meta | 8 + .../UI/Core/UIControls/AnimationTriggers.cs | 36 + .../UI/Core/UIControls/AnimationTriggers.cs.meta | 11 + .../UnityEngine.UI/UI/Core/UIControls/Button.cs | 83 + .../UI/Core/UIControls/Button.cs.meta | 11 + .../UI/Core/UIControls/ColorBlock.cs | 91 + .../UI/Core/UIControls/ColorBlock.cs.meta | 11 + .../UI/Core/UIControls/DefaultControls.cs | 581 +++++ .../UI/Core/UIControls/DefaultControls.cs.meta | 11 + .../UnityEngine.UI/UI/Core/UIControls/Dropdown.cs | 649 +++++ .../UI/Core/UIControls/Dropdown.cs.meta | 11 + .../UI/Core/UIControls/InputField.cs | 2484 ++++++++++++++++++++ .../UI/Core/UIControls/InputField.cs.meta | 11 + .../UI/Core/UIControls/Navigation.cs | 74 + .../UI/Core/UIControls/Navigation.cs.meta | 11 + .../UI/Core/UIControls/ScrollRect.cs | 873 +++++++ .../UI/Core/UIControls/ScrollRect.cs.meta | 11 + .../UnityEngine.UI/UI/Core/UIControls/Scrollbar.cs | 422 ++++ .../UI/Core/UIControls/Scrollbar.cs.meta | 11 + .../UI/Core/UIControls/Selectable.cs | 672 ++++++ .../UI/Core/UIControls/Selectable.cs.meta | 11 + .../UnityEngine.UI/UI/Core/UIControls/Slider.cs | 450 ++++ .../UI/Core/UIControls/Slider.cs.meta | 11 + .../UnityEngine.UI/UI/Core/UIControls/Toggle.cs | 246 ++ .../UI/Core/UIControls/Toggle.cs.meta | 11 + .../UI/Core/UIControls/ToggleGroup.cs | 73 + .../UI/Core/UIControls/ToggleGroup.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Utility.meta | 10 + .../UnityEngine.UI/UI/Core/Utility/ListPool.cs | 22 + .../UI/Core/Utility/ListPool.cs.meta | 13 + .../UnityEngine.UI/UI/Core/Utility/ObjectPool.cs | 48 + .../UI/Core/Utility/ObjectPool.cs.meta | 13 + .../UI/Core/Utility/ReflectionMethodsCache.cs | 53 + .../UI/Core/Utility/ReflectionMethodsCache.cs.meta | 13 + .../UI/Core/Utility/SetPropertyUtility.cs | 36 + .../UI/Core/Utility/SetPropertyUtility.cs.meta | 11 + .../UnityEngine.UI/UI/Core/Utility/VertexHelper.cs | 194 ++ .../UI/Core/Utility/VertexHelper.cs.meta | 13 + .../UnityEngine.UI/UI/Core/VertexModifiers.meta | 10 + .../UI/Core/VertexModifiers/BaseMeshEffect.cs | 74 + .../UI/Core/VertexModifiers/BaseMeshEffect.cs.meta | 13 + .../UI/Core/VertexModifiers/IMeshModifier.cs | 20 + .../UI/Core/VertexModifiers/IMeshModifier.cs.meta | 13 + .../UI/Core/VertexModifiers/Outline.cs | 44 + .../UI/Core/VertexModifiers/Outline.cs.meta | 13 + .../UI/Core/VertexModifiers/PositionAsUV1.cs | 22 + .../UI/Core/VertexModifiers/PositionAsUV1.cs.meta | 13 + .../UI/Core/VertexModifiers/Shadow.cs | 126 + .../UI/Core/VertexModifiers/Shadow.cs.meta | 13 + 132 files changed, 14710 insertions(+) create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/DefaultControls.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/DefaultControls.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Dropdown.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Dropdown.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/InputField.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/InputField.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Navigation.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Navigation.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ScrollRect.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ScrollRect.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Scrollbar.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Scrollbar.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Selectable.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Selectable.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Slider.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Slider.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Toggle.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Toggle.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ToggleGroup.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ToggleGroup.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/ListPool.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/ListPool.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/ObjectPool.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/ObjectPool.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/ReflectionMethodsCache.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/ReflectionMethodsCache.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/SetPropertyUtility.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/SetPropertyUtility.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/VertexHelper.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Utility/VertexHelper.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/BaseMeshEffect.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/BaseMeshEffect.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/IMeshModifier.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/IMeshModifier.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/Outline.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/Outline.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/PositionAsUV1.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/PositionAsUV1.cs.meta create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/Shadow.cs create mode 100644 Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/VertexModifiers/Shadow.cs.meta (limited to 'Assets/uGUI-2017.1/UnityEngine.UI/UI/Core') diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs new file mode 100644 index 0000000..200b4e5 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs @@ -0,0 +1,307 @@ +using System; +using System.Collections.Generic; +using UnityEngine.UI.Collections; + +namespace UnityEngine.UI +{ + // canvas的不同阶段,用来设置layout、graphic做不同的事情,具体看CanvasUpdateRegistry + // prelayout -> layout -> postlayout -> prerender -> laterender =>=>=> render + public enum CanvasUpdate + { + Prelayout = 0, + Layout = 1, + PostLayout = 2, + PreRender = 3, + LatePreRender = 4, + + MaxUpdateValue = 5 + } + + public interface ICanvasElement + { + Transform transform { get; } + void Rebuild(CanvasUpdate executing); + void LayoutComplete(); + void GraphicUpdateComplete(); + // due to unity overriding null check + // we need this as something may not be null + // but may be destroyed + bool IsDestroyed(); + } + + // 需要注意整个游戏只有一个单例 + public class CanvasUpdateRegistry + { + private static CanvasUpdateRegistry s_Instance; + + private bool m_PerformingLayoutUpdate; + private bool m_PerformingGraphicUpdate; + + private readonly IndexedSet m_LayoutRebuildQueue = new IndexedSet(); + private readonly IndexedSet m_GraphicRebuildQueue = new IndexedSet(); + + protected CanvasUpdateRegistry() + { + // willRenderCanvases在渲染canvas之前调用,执行PerformUpdate来Rebuild处理m_LayoutRebuildQueue和m_GraphicRebuildQueue + Canvas.willRenderCanvases += PerformUpdate; + } + + // 简单单例 + public static CanvasUpdateRegistry instance + { + get + { + if (s_Instance == null) + s_Instance = new CanvasUpdateRegistry(); + return s_Instance; + } + } + + // 检查一下实现了ICanvasElement的对象合法性,实现了ICanvasElement接口的对象必须是Unity Object, + private bool ObjectValidForUpdate(ICanvasElement element) + { + var valid = element != null; + + var isUnityObject = element is Object; + if (isUnityObject) + valid = (element as Object) != null; //Here we make use of the overloaded UnityEngine.Object == null, that checks if the native object is alive. + + return valid; + } + + private void CleanInvalidItems() + { + // So MB's override the == operator for null equality, which checks + // if they are destroyed. This is fine if you are looking at a concrete + // mb, but in this case we are looking at a list of ICanvasElement + // this won't forward the == operator to the MB, but just check if the + // interface is null. IsDestroyed will return if the backend is destroyed. + + for (int i = m_LayoutRebuildQueue.Count - 1; i >= 0; --i) + { + var item = m_LayoutRebuildQueue[i]; + if (item == null) + { + m_LayoutRebuildQueue.RemoveAt(i); + continue; + } + + if (item.IsDestroyed()) + { + m_LayoutRebuildQueue.RemoveAt(i); + item.LayoutComplete(); + } + } + + for (int i = m_GraphicRebuildQueue.Count - 1; i >= 0; --i) + { + var item = m_GraphicRebuildQueue[i]; + if (item == null) + { + m_GraphicRebuildQueue.RemoveAt(i); + continue; + } + + if (item.IsDestroyed()) + { + m_GraphicRebuildQueue.RemoveAt(i); + item.GraphicUpdateComplete(); + } + } + } + + private static readonly Comparison s_SortLayoutFunction = SortLayoutList; + // 在渲染canvas之前对canvas下的元素进行rebuild + // 进行 prelayout -> layout -> postlayout -> prerender -> LatePreRender 流程 + private void PerformUpdate() + { + UISystemProfilerApi.BeginSample(UISystemProfilerApi.SampleType.Layout); + CleanInvalidItems(); + + m_PerformingLayoutUpdate = true; + + // 重建layout + + // 根据父节点从少到多排序,先布局父节点少的,由少到多,由内到外 + m_LayoutRebuildQueue.Sort(s_SortLayoutFunction); + // prelayout -> layout -> postlayout + for (int i = 0; i <= (int)CanvasUpdate.PostLayout; i++) // 不同的阶段 + { + for (int j = 0; j < m_LayoutRebuildQueue.Count; j++) + { + var rebuild = instance.m_LayoutRebuildQueue[j]; + try + { + if (ObjectValidForUpdate(rebuild)) + rebuild.Rebuild((CanvasUpdate)i); + } + catch (Exception e) + { + Debug.LogException(e, rebuild.transform); + } + } + } + + // 布局完成 + for (int i = 0; i < m_LayoutRebuildQueue.Count; ++i) + m_LayoutRebuildQueue[i].LayoutComplete(); + + // 清空队列,重置状态 + instance.m_LayoutRebuildQueue.Clear(); + m_PerformingLayoutUpdate = false; + + // 做剔除+裁剪 + // now layout is complete do culling... + ClipperRegistry.instance.Cull(); + + // 重建graphic + + m_PerformingGraphicUpdate = true; + // prerender -> lateprerender + for (var i = (int)CanvasUpdate.PreRender; i < (int)CanvasUpdate.MaxUpdateValue; i++) + { + for (var k = 0; k < instance.m_GraphicRebuildQueue.Count; k++) + { + try + { + var element = instance.m_GraphicRebuildQueue[k]; + if (ObjectValidForUpdate(element)) + element.Rebuild((CanvasUpdate)i); + } + catch (Exception e) + { + Debug.LogException(e, instance.m_GraphicRebuildQueue[k].transform); + } + } + } + + // graphic设置mesh和材质完成 + for (int i = 0; i < m_GraphicRebuildQueue.Count; ++i) + m_GraphicRebuildQueue[i].GraphicUpdateComplete(); + + // 清空队列,重置状态 + instance.m_GraphicRebuildQueue.Clear(); + m_PerformingGraphicUpdate = false; + + // 到了这里布局和网格、材质都设置完毕,后面canvas会渲染 + + // profiler不用管 + UISystemProfilerApi.EndSample(UISystemProfilerApi.SampleType.Layout); + } + + // 统计父节点个数 + private static int ParentCount(Transform child) + { + if (child == null) + return 0; + + var parent = child.parent; + int count = 0; + while (parent != null) + { + count++; + parent = parent.parent; + } + return count; + } + + // 根据父节点由少到多排序 + private static int SortLayoutList(ICanvasElement x, ICanvasElement y) + { + Transform t1 = x.transform; + Transform t2 = y.transform; + + return ParentCount(t1) - ParentCount(t2); + } + + public static bool IsRebuildingLayout() + { + return instance.m_PerformingLayoutUpdate; + } + + public static bool IsRebuildingGraphics() + { + return instance.m_PerformingGraphicUpdate; + } + +#region 将canvas elements注册到队列里的方法 + + public static void RegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + instance.InternalRegisterCanvasElementForLayoutRebuild(element); + } + + public static bool TryRegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + return instance.InternalRegisterCanvasElementForLayoutRebuild(element); + } + + private bool InternalRegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + if (m_LayoutRebuildQueue.Contains(element)) + return false; + + /* TODO: this likely should be here but causes the error to show just resizing the game view (case 739376) + if (m_PerformingLayoutUpdate) + { + Debug.LogError(string.Format("Trying to add {0} for layout rebuild while we are already inside a layout rebuild loop. This is not supported.", element)); + return false; + }*/ + + return m_LayoutRebuildQueue.AddUnique(element); + } + + public static void RegisterCanvasElementForGraphicRebuild(ICanvasElement element) + { + instance.InternalRegisterCanvasElementForGraphicRebuild(element); + } + + public static bool TryRegisterCanvasElementForGraphicRebuild(ICanvasElement element) + { + return instance.InternalRegisterCanvasElementForGraphicRebuild(element); + } + + private bool InternalRegisterCanvasElementForGraphicRebuild(ICanvasElement element) + { + if (m_PerformingGraphicUpdate) + { + Debug.LogError(string.Format("Trying to add {0} for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.", element)); + return false; + } + + return m_GraphicRebuildQueue.AddUnique(element); + } + + public static void UnRegisterCanvasElementForRebuild(ICanvasElement element) + { + instance.InternalUnRegisterCanvasElementForLayoutRebuild(element); + instance.InternalUnRegisterCanvasElementForGraphicRebuild(element); + } + + private void InternalUnRegisterCanvasElementForLayoutRebuild(ICanvasElement element) + { + if (m_PerformingLayoutUpdate) + { + Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); + return; + } + + element.LayoutComplete(); + instance.m_LayoutRebuildQueue.Remove(element); + } + + private void InternalUnRegisterCanvasElementForGraphicRebuild(ICanvasElement element) + { + if (m_PerformingGraphicUpdate) + { + Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); + return; + } + element.GraphicUpdateComplete(); + instance.m_GraphicRebuildQueue.Remove(element); + } + +#endregion + + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs.meta new file mode 100644 index 0000000..be77e1d --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/CanvasUpdateRegistry.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b607eb8b4c72f944c9fda5d106491067 +timeCreated: 1602119379 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling.meta new file mode 100644 index 0000000..2b86263 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 2f77b3d02da9eb145be1dfc4c8684a80 +folderAsset: yes +timeCreated: 1602119280 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs new file mode 100644 index 0000000..ea7f527 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using UnityEngine.UI.Collections; + +namespace UnityEngine.UI +{ + public class ClipperRegistry + { + static ClipperRegistry s_Instance; + + readonly IndexedSet m_Clippers = new IndexedSet(); + + protected ClipperRegistry() + { + // This is needed for AOT platforms. Without it the compile doesn't get the definition of the Dictionarys +#pragma warning disable 168 + Dictionary emptyIClipperDic; +#pragma warning restore 168 + } + + public static ClipperRegistry instance + { + get + { + if (s_Instance == null) + s_Instance = new ClipperRegistry(); + return s_Instance; + } + } + + public void Cull() + { + for (var i = 0; i < m_Clippers.Count; ++i) + { + m_Clippers[i].PerformClipping(); + } + } + + public static void Register(IClipper c) + { + if (c == null) + return; + instance.m_Clippers.AddUnique(c); + } + + public static void Unregister(IClipper c) + { + instance.m_Clippers.Remove(c); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs.meta new file mode 100644 index 0000000..32995ae --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/ClipperRegistry.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b494fa40405522d49af6bca6e68e4ba6 +timeCreated: 1602119379 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs new file mode 100644 index 0000000..7dd39bf --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; + +namespace UnityEngine.UI +{ + public static class Clipping + { + public static Rect FindCullAndClipWorldRect(List rectMaskParents, out bool validRect) + { + if (rectMaskParents.Count == 0) + { + validRect = false; + return new Rect(); + } + + var compoundRect = rectMaskParents[0].canvasRect; + for (var i = 0; i < rectMaskParents.Count; ++i) + compoundRect = RectIntersect(compoundRect, rectMaskParents[i].canvasRect); + + var cull = compoundRect.width <= 0 || compoundRect.height <= 0; + if (cull) + { + validRect = false; + return new Rect(); + } + + Vector3 point1 = new Vector3(compoundRect.x, compoundRect.y, 0.0f); + Vector3 point2 = new Vector3(compoundRect.x + compoundRect.width, compoundRect.y + compoundRect.height, 0.0f); + validRect = true; + return new Rect(point1.x, point1.y, point2.x - point1.x, point2.y - point1.y); + } + + // 计算矩形交集 + private static Rect RectIntersect(Rect a, Rect b) + { + float xMin = Mathf.Max(a.x, b.x); + float xMax = Mathf.Min(a.x + a.width, b.x + b.width); + float yMin = Mathf.Max(a.y, b.y); + float yMax = Mathf.Min(a.y + a.height, b.y + b.height); + if (xMax >= xMin && yMax >= yMin) + return new Rect(xMin, yMin, xMax - xMin, yMax - yMin); + return new Rect(0f, 0f, 0f, 0f); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs.meta new file mode 100644 index 0000000..698e06f --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/Clipping.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 88fc11e9a11bf1941abc08b9ed323b6f +timeCreated: 1602119379 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs new file mode 100644 index 0000000..4593f17 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs @@ -0,0 +1,16 @@ +namespace UnityEngine.UI +{ + public interface IClipper + { + void PerformClipping(); + } + + public interface IClippable + { + GameObject gameObject { get; } + void RecalculateClipping(); + RectTransform rectTransform { get; } + void Cull(Rect clipRect, bool validRect); + void SetClipRect(Rect value, bool validRect); + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs.meta new file mode 100644 index 0000000..1852869 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/IClipRegion.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d395da6bc4c1e6f4b9521bb99b22f3b4 +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs new file mode 100644 index 0000000..6d12322 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs @@ -0,0 +1,21 @@ +namespace UnityEngine.UI +{ + internal class RectangularVertexClipper + { + readonly Vector3[] m_WorldCorners = new Vector3[4]; + readonly Vector3[] m_CanvasCorners = new Vector3[4]; + + public Rect GetCanvasRect(RectTransform t, Canvas c) + { + if (c == null) + return new Rect(); + + t.GetWorldCorners(m_WorldCorners); + var canvasTransform = c.GetComponent(); + for (int i = 0; i < 4; ++i) + m_CanvasCorners[i] = canvasTransform.InverseTransformPoint(m_WorldCorners[i]); + + return new Rect(m_CanvasCorners[0].x, m_CanvasCorners[0].y, m_CanvasCorners[2].x - m_CanvasCorners[0].x, m_CanvasCorners[2].y - m_CanvasCorners[0].y); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs.meta new file mode 100644 index 0000000..f33cd90 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Culling/RectangularVertexClipper.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 545014a8997364a47b344095371a7332 +timeCreated: 1602119378 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font.meta new file mode 100644 index 0000000..28b5ef6 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 680fe3dddba51f54ca833b46dc6b5a82 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs new file mode 100644 index 0000000..3a85af1 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs @@ -0,0 +1,158 @@ +using System; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + /// + /// Labels reference specific font data used to draw them. This class contains that data. + /// + + [Serializable] + public class FontData : ISerializationCallbackReceiver + { + [SerializeField] + [FormerlySerializedAs("font")] + private Font m_Font; + + [SerializeField] + [FormerlySerializedAs("fontSize")] + private int m_FontSize; + + [SerializeField] + [FormerlySerializedAs("fontStyle")] + private FontStyle m_FontStyle; + + [SerializeField] + private bool m_BestFit; + + [SerializeField] + private int m_MinSize; + + [SerializeField] + private int m_MaxSize; + + [SerializeField] + [FormerlySerializedAs("alignment")] + private TextAnchor m_Alignment; + + [SerializeField] + private bool m_AlignByGeometry; + + [SerializeField] + [FormerlySerializedAs("richText")] + private bool m_RichText; + + [SerializeField] + private HorizontalWrapMode m_HorizontalOverflow; + + [SerializeField] + private VerticalWrapMode m_VerticalOverflow; + + [SerializeField] + private float m_LineSpacing; + + public static FontData defaultFontData + { + get + { + var fontData = new FontData + { + m_FontSize = 14, + m_LineSpacing = 1f, + m_FontStyle = FontStyle.Normal, + m_BestFit = false, + m_MinSize = 10, + m_MaxSize = 40, + m_Alignment = TextAnchor.UpperLeft, + m_HorizontalOverflow = HorizontalWrapMode.Wrap, + m_VerticalOverflow = VerticalWrapMode.Truncate, + m_RichText = true, + m_AlignByGeometry = false + }; + return fontData; + } + } + + public Font font + { + get { return m_Font; } + set { m_Font = value; } + } + + public int fontSize + { + get { return m_FontSize; } + set { Debug.Log("FontData.fontSize"); m_FontSize = value; } + } + + public FontStyle fontStyle + { + get { return m_FontStyle; } + set { m_FontStyle = value; } + } + + public bool bestFit + { + get { return m_BestFit; } + set { m_BestFit = value; } + } + + public int minSize + { + get { return m_MinSize; } + set { m_MinSize = value; } + } + + public int maxSize + { + get { return m_MaxSize; } + set { m_MaxSize = value; } + } + + public TextAnchor alignment + { + get { return m_Alignment; } + set { m_Alignment = value; } + } + + public bool alignByGeometry + { + get { return m_AlignByGeometry; } + set { m_AlignByGeometry = value; } + } + + public bool richText + { + get { return m_RichText; } + set { m_RichText = value; } + } + + public HorizontalWrapMode horizontalOverflow + { + get { return m_HorizontalOverflow; } + set { m_HorizontalOverflow = value; } + } + + public VerticalWrapMode verticalOverflow + { + get { return m_VerticalOverflow; } + set { m_VerticalOverflow = value; } + } + + public float lineSpacing + { + get { return m_LineSpacing; } + set { m_LineSpacing = value; } + } + + void ISerializationCallbackReceiver.OnBeforeSerialize() + {} + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + m_FontSize = Mathf.Clamp(m_FontSize, 0, 300); + m_MinSize = Mathf.Clamp(m_MinSize, 0, m_FontSize); + m_MaxSize = Mathf.Clamp(m_MaxSize, m_FontSize, 300); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs.meta new file mode 100644 index 0000000..f4bb2a1 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontData.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 7c47b221885e53f479140fc48712f249 +timeCreated: 1602119379 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs new file mode 100644 index 0000000..a63d62b --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityEngine.UI +{ + // 全局记录使用了某个Font字体的所有Text,当这个Font的GlyphAtlas大小改变的时候通知这些Text重建mesh(更新UV) + // 因为GlyphAtlas大小改变了,原先的UV已经不对了 + public static class FontUpdateTracker + { + static Dictionary> m_Tracked = new Dictionary>(); + + public static void TrackText(Text t) + { + if (t.font == null) + return; + + HashSet exists; + m_Tracked.TryGetValue(t.font, out exists); + if (exists == null) + { + // font texture重新生成的时候会调这个回调,然后需要Text组件重建mesh的UV数据,因为原先的fontGlyph里的UV已经不准了 + // https://docs.unity3d.com/ScriptReference/Font-textureRebuilt.html + // The textureRebuilt event is global for all fonts, so we add our delegate the first time we register *any* Text + if (m_Tracked.Count == 0) + Font.textureRebuilt += RebuildForFont; + + exists = new HashSet(); + m_Tracked.Add(t.font, exists); + } + + if (!exists.Contains(t)) + exists.Add(t); + } + + private static void RebuildForFont(Font f) + { + HashSet texts; + m_Tracked.TryGetValue(f, out texts); + + if (texts == null) + return; + + foreach (var text in texts) + text.FontTextureChanged(); + } + + public static void UntrackText(Text t) + { + if (t.font == null) + return; + + HashSet texts; + m_Tracked.TryGetValue(t.font, out texts); + + if (texts == null) + return; + + texts.Remove(t); + + if (texts.Count == 0) + { + m_Tracked.Remove(t.font); + + // There is a global textureRebuilt event for all fonts, so once the last Text reference goes away, remove our delegate + if (m_Tracked.Count == 0) + Font.textureRebuilt -= RebuildForFont; + } + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs.meta new file mode 100644 index 0000000..8e6ddeb --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/FontUpdateTracker.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fba9c6c6325db2d49bdf2b608066f0e0 +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs new file mode 100644 index 0000000..3d3d17b --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs @@ -0,0 +1,576 @@ +using System; +using System.Collections.Generic; + +namespace UnityEngine.UI +{ + /// + /// Labels are graphics that display text. + /// + + [AddComponentMenu("UI/Text", 10)] + public class Text : MaskableGraphic, ILayoutElement + { + [SerializeField] private FontData m_FontData = FontData.defaultFontData; + +#if UNITY_EDITOR + // needed to track font changes from the inspector + private Font m_LastTrackedFont; +#endif + + [TextArea(3, 10)][SerializeField] protected string m_Text = String.Empty; + + private TextGenerator m_TextCache; + private TextGenerator m_TextCacheForLayout; + + static protected Material s_DefaultText = null; + + // We use this flag instead of Unregistering/Registering the callback to avoid allocation. + [NonSerialized] protected bool m_DisableFontTextureRebuiltCallback = false; + + protected Text() + { + useLegacyMeshGeneration = false; + } + + // text generator,得到字符串在glyph atlas中的UV,构建mesh + /// + /// Get or set the material used by this Text. + /// + + public TextGenerator cachedTextGenerator + { + get { return m_TextCache ?? (m_TextCache = (m_Text.Length != 0 ? new TextGenerator(m_Text.Length) : new TextGenerator())); } + } + + public TextGenerator cachedTextGeneratorForLayout + { + get { return m_TextCacheForLayout ?? (m_TextCacheForLayout = new TextGenerator()); } + } + + /// + /// Text's texture comes from the font. + /// + public override Texture mainTexture + { + get + { + if (font != null && font.material != null && font.material.mainTexture != null) + return font.material.mainTexture; + + if (m_Material != null) + return m_Material.mainTexture; + + return base.mainTexture; + } + } + + public void FontTextureChanged() + { + // Only invoke if we are not destroyed. + if (!this) + return; + + if (m_DisableFontTextureRebuiltCallback) + return; + + cachedTextGenerator.Invalidate(); + + if (!IsActive()) + return; + + // this is a bit hacky, but it is currently the + // cleanest solution.... + // if we detect the font texture has changed and are in a rebuild loop + // we just regenerate the verts for the new UV's + if (CanvasUpdateRegistry.IsRebuildingGraphics() || CanvasUpdateRegistry.IsRebuildingLayout()) + UpdateGeometry(); + else + SetAllDirty(); + } + + public Font font + { + get + { + return m_FontData.font; + } + set + { + if (m_FontData.font == value) + return; + + FontUpdateTracker.UntrackText(this); + + m_FontData.font = value; + + FontUpdateTracker.TrackText(this); + +#if UNITY_EDITOR + // needed to track font changes from the inspector + m_LastTrackedFont = value; +#endif + + SetAllDirty(); + } + } + + /// + /// Text that's being displayed by the Text. + /// + + public virtual string text + { + get + { + return m_Text; + } + set + { + if (String.IsNullOrEmpty(value)) + { + if (String.IsNullOrEmpty(m_Text)) + return; + m_Text = ""; + SetVerticesDirty(); + } + else if (m_Text != value) + { + m_Text = value; + SetVerticesDirty(); + SetLayoutDirty(); + } + } + } + + /// + /// Whether this Text will support rich text. + /// + + public bool supportRichText + { + get + { + return m_FontData.richText; + } + set + { + if (m_FontData.richText == value) + return; + m_FontData.richText = value; + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + /// + /// Wrap mode used by the text. + /// + + public bool resizeTextForBestFit + { + get + { + return m_FontData.bestFit; + } + set + { + if (m_FontData.bestFit == value) + return; + m_FontData.bestFit = value; + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + public int resizeTextMinSize + { + get + { + return m_FontData.minSize; + } + set + { + if (m_FontData.minSize == value) + return; + m_FontData.minSize = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + public int resizeTextMaxSize + { + get + { + return m_FontData.maxSize; + } + set + { + if (m_FontData.maxSize == value) + return; + m_FontData.maxSize = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + /// + /// Alignment anchor used by the text. + /// + + public TextAnchor alignment + { + get + { + return m_FontData.alignment; + } + set + { + if (m_FontData.alignment == value) + return; + m_FontData.alignment = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + public bool alignByGeometry + { + get + { + return m_FontData.alignByGeometry; + } + set + { + if (m_FontData.alignByGeometry == value) + return; + m_FontData.alignByGeometry = value; + + SetVerticesDirty(); + } + } + + public int fontSize + { + get + { + return m_FontData.fontSize; + } + set + { + // font size改变的时候重建mesh + if (m_FontData.fontSize == value) + return; + m_FontData.fontSize = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + public HorizontalWrapMode horizontalOverflow + { + get + { + return m_FontData.horizontalOverflow; + } + set + { + if (m_FontData.horizontalOverflow == value) + return; + m_FontData.horizontalOverflow = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + public VerticalWrapMode verticalOverflow + { + get + { + return m_FontData.verticalOverflow; + } + set + { + if (m_FontData.verticalOverflow == value) + return; + m_FontData.verticalOverflow = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + public float lineSpacing + { + get + { + return m_FontData.lineSpacing; + } + set + { + if (m_FontData.lineSpacing == value) + return; + m_FontData.lineSpacing = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + /// + /// Font style used by the Text's text. + /// + + public FontStyle fontStyle + { + get + { + return m_FontData.fontStyle; + } + set + { + if (m_FontData.fontStyle == value) + return; + m_FontData.fontStyle = value; + + SetVerticesDirty(); + SetLayoutDirty(); + } + } + + public float pixelsPerUnit + { + get + { + var localCanvas = canvas; + if (!localCanvas) + return 1; + // For dynamic fonts, ensure we use one pixel per pixel on the screen. + if (!font || font.dynamic) + return localCanvas.scaleFactor; + // For non-dynamic fonts, calculate pixels per unit based on specified font size relative to font object's own font size. + if (m_FontData.fontSize <= 0 || font.fontSize <= 0) + return 1; + return font.fontSize / (float)m_FontData.fontSize; + } + } + + protected override void OnEnable() + { + base.OnEnable(); + cachedTextGenerator.Invalidate(); + FontUpdateTracker.TrackText(this); + } + + protected override void OnDisable() + { + FontUpdateTracker.UntrackText(this); + base.OnDisable(); + } + + protected override void UpdateGeometry() + { + if (font != null) + { + base.UpdateGeometry(); + } + } + +#if UNITY_EDITOR + protected override void Reset() + { + AssignDefaultFont(); + } + +#endif + internal void AssignDefaultFont() + { + font = Resources.GetBuiltinResource("Arial.ttf"); + } + + // 根据FontData设置TextGenerationSettings + public TextGenerationSettings GetGenerationSettings(Vector2 extents) + { + var settings = new TextGenerationSettings(); + + settings.generationExtents = extents; + if (font != null && font.dynamic) + { + settings.fontSize = m_FontData.fontSize; + settings.resizeTextMinSize = m_FontData.minSize; + settings.resizeTextMaxSize = m_FontData.maxSize; + } + + // Other settings + settings.textAnchor = m_FontData.alignment; + settings.alignByGeometry = m_FontData.alignByGeometry; + settings.scaleFactor = pixelsPerUnit; + settings.color = color; // 这里是顶点颜色 + settings.font = font; + settings.pivot = rectTransform.pivot; + settings.richText = m_FontData.richText; + settings.lineSpacing = m_FontData.lineSpacing; + settings.fontStyle = m_FontData.fontStyle; + settings.resizeTextForBestFit = m_FontData.bestFit; + settings.updateBounds = false; + settings.horizontalOverflow = m_FontData.horizontalOverflow; + settings.verticalOverflow = m_FontData.verticalOverflow; + + return settings; + } + + static public Vector2 GetTextAnchorPivot(TextAnchor anchor) + { + switch (anchor) + { + case TextAnchor.LowerLeft: return new Vector2(0, 0); + case TextAnchor.LowerCenter: return new Vector2(0.5f, 0); + case TextAnchor.LowerRight: return new Vector2(1, 0); + case TextAnchor.MiddleLeft: return new Vector2(0, 0.5f); + case TextAnchor.MiddleCenter: return new Vector2(0.5f, 0.5f); + case TextAnchor.MiddleRight: return new Vector2(1, 0.5f); + case TextAnchor.UpperLeft: return new Vector2(0, 1); + case TextAnchor.UpperCenter: return new Vector2(0.5f, 1); + case TextAnchor.UpperRight: return new Vector2(1, 1); + default: return Vector2.zero; + } + } + + readonly UIVertex[] m_TempVerts = new UIVertex[4]; + protected override void OnPopulateMesh(VertexHelper toFill) + { + if (font == null) + return; + + // We don't care if we the font Texture changes while we are doing our Update. + // The end result of cachedTextGenerator will be valid for this instance. + // Otherwise we can get issues like Case 619238. + m_DisableFontTextureRebuiltCallback = true; + + Vector2 extents = rectTransform.rect.size; + + // 生成对应的网格数据(顶点、UV) + var settings = GetGenerationSettings(extents); + cachedTextGenerator.PopulateWithErrors(text, settings, gameObject); + + // Apply the offset to the vertices + IList verts = cachedTextGenerator.verts; + float unitsPerPixel = 1 / pixelsPerUnit; + //Last 4 verts are always a new line... (\n) + int vertCount = verts.Count - 4; + + Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel; + roundingOffset = PixelAdjustPoint(roundingOffset) - roundingOffset; + toFill.Clear(); + if (roundingOffset != Vector2.zero) + { + for (int i = 0; i < vertCount; ++i) + { + int tempVertsIndex = i & 3; + m_TempVerts[tempVertsIndex] = verts[i]; + m_TempVerts[tempVertsIndex].position *= unitsPerPixel; + m_TempVerts[tempVertsIndex].position.x += roundingOffset.x; + m_TempVerts[tempVertsIndex].position.y += roundingOffset.y; + if (tempVertsIndex == 3) + toFill.AddUIVertexQuad(m_TempVerts); + } + } + else + { + for (int i = 0; i < vertCount; ++i) + { + int tempVertsIndex = i & 3; + m_TempVerts[tempVertsIndex] = verts[i]; + m_TempVerts[tempVertsIndex].position *= unitsPerPixel; + if (tempVertsIndex == 3) + toFill.AddUIVertexQuad(m_TempVerts); + } + } + + m_DisableFontTextureRebuiltCallback = false; + } + + public virtual void CalculateLayoutInputHorizontal() {} + public virtual void CalculateLayoutInputVertical() {} + + public virtual float minWidth + { + get { return 0; } + } + + public virtual float preferredWidth + { + get + { + var settings = GetGenerationSettings(Vector2.zero); + return cachedTextGeneratorForLayout.GetPreferredWidth(m_Text, settings) / pixelsPerUnit; + } + } + + public virtual float flexibleWidth { get { return -1; } } + + public virtual float minHeight + { + get { return 0; } + } + + public virtual float preferredHeight + { + get + { + var settings = GetGenerationSettings(new Vector2(GetPixelAdjustedRect().size.x, 0.0f)); + return cachedTextGeneratorForLayout.GetPreferredHeight(m_Text, settings) / pixelsPerUnit; + } + } + + public virtual float flexibleHeight { get { return -1; } } + + public virtual int layoutPriority { get { return 0; } } + +#if UNITY_EDITOR + public override void OnRebuildRequested() + { + // After a Font asset gets re-imported the managed side gets deleted and recreated, + // that means the delegates are not persisted. + // so we need to properly enforce a consistent state here. + FontUpdateTracker.UntrackText(this); + FontUpdateTracker.TrackText(this); + + // Also the textgenerator is no longer valid. + cachedTextGenerator.Invalidate(); + + base.OnRebuildRequested(); + } + + // 当编辑器里修改了参数值的时候调这个回调,setDirty,后续重建mesh + // The Text inspector editor can change the font, and we need a way to track changes so that we get the appropriate rebuild callbacks + // We can intercept changes in OnValidate, and keep track of the previous font reference + protected override void OnValidate() + { + if (!IsActive()) + { + base.OnValidate(); + return; + } + + if (m_FontData.font != m_LastTrackedFont) + { + Font newFont = m_FontData.font; + m_FontData.font = m_LastTrackedFont; + FontUpdateTracker.UntrackText(this); + m_FontData.font = newFont; + FontUpdateTracker.TrackText(this); + + m_LastTrackedFont = newFont; + } + base.OnValidate(); + } + +#endif // if UNITY_EDITOR + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs.meta new file mode 100644 index 0000000..ea6d1d8 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Font/Text.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48696ad002dcb2146ab8d6ad72d455d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics.meta new file mode 100644 index 0000000..f28155d --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 68d41682b219698458518d531a2805cc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs new file mode 100644 index 0000000..21acfb4 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs @@ -0,0 +1,669 @@ +using System; +#if UNITY_EDITOR +using System.Reflection; +#endif +using UnityEngine.Events; +using UnityEngine.EventSystems; +using UnityEngine.Serialization; +using UnityEngine.UI.CoroutineTween; + +namespace UnityEngine.UI +{ + /// + /// Base class for all UI components that should be derived from when creating new Graphic types. + /// + [DisallowMultipleComponent] + [RequireComponent(typeof(CanvasRenderer))] + [RequireComponent(typeof(RectTransform))] + [ExecuteInEditMode] + public abstract class Graphic + : UIBehaviour, + ICanvasElement + { + static protected Material s_DefaultUI = null; + static protected Texture2D s_WhiteTexture = null; + + /// + /// Default material used to draw everything if no explicit material was specified. + /// + + static public Material defaultGraphicMaterial + { + get + { + if (s_DefaultUI == null) + s_DefaultUI = Canvas.GetDefaultCanvasMaterial(); + return s_DefaultUI; + } + } + + // Cached and saved values + [FormerlySerializedAs("m_Mat")] + [SerializeField] protected Material m_Material; + + [SerializeField] private Color m_Color = Color.white; + public virtual Color color { get { return m_Color; } set { if (SetPropertyUtility.SetColor(ref m_Color, value)) SetVerticesDirty(); } } + + [SerializeField] private bool m_RaycastTarget = true; + public virtual bool raycastTarget { get { return m_RaycastTarget; } set { m_RaycastTarget = value; } } + + [NonSerialized] private RectTransform m_RectTransform; + [NonSerialized] private CanvasRenderer m_CanvasRender; + [NonSerialized] private Canvas m_Canvas; + + [NonSerialized] private bool m_VertsDirty; + [NonSerialized] private bool m_MaterialDirty; + + [NonSerialized] protected UnityAction m_OnDirtyLayoutCallback; + [NonSerialized] protected UnityAction m_OnDirtyVertsCallback; + [NonSerialized] protected UnityAction m_OnDirtyMaterialCallback; + + [NonSerialized] protected static Mesh s_Mesh; + [NonSerialized] private static readonly VertexHelper s_VertexHelper = new VertexHelper(); + + // Tween controls for the Graphic + [NonSerialized] + private readonly TweenRunner m_ColorTweenRunner; + + protected bool useLegacyMeshGeneration { get; set; } + + // Called by Unity prior to deserialization, + // should not be called by users + protected Graphic() + { + if (m_ColorTweenRunner == null) + m_ColorTweenRunner = new TweenRunner(); + m_ColorTweenRunner.Init(this); + useLegacyMeshGeneration = true; + } + + public virtual void SetAllDirty() + { + SetLayoutDirty(); + SetVerticesDirty(); + SetMaterialDirty(); + } + + public virtual void SetLayoutDirty() + { + if (!IsActive()) + return; + + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + + if (m_OnDirtyLayoutCallback != null) + m_OnDirtyLayoutCallback(); + } + + public virtual void SetVerticesDirty() + { + if (!IsActive()) + return; + + m_VertsDirty = true; + CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); + + if (m_OnDirtyVertsCallback != null) + m_OnDirtyVertsCallback(); + } + + public virtual void SetMaterialDirty() + { + if (!IsActive()) + return; + + m_MaterialDirty = true; + CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); + + if (m_OnDirtyMaterialCallback != null) + m_OnDirtyMaterialCallback(); + } + + protected override void OnRectTransformDimensionsChange() + { + if (gameObject.activeInHierarchy) + { + // prevent double dirtying... + if (CanvasUpdateRegistry.IsRebuildingLayout()) + SetVerticesDirty(); + else + { + SetVerticesDirty(); + SetLayoutDirty(); + } + } + } + + protected override void OnBeforeTransformParentChanged() + { + GraphicRegistry.UnregisterGraphicForCanvas(canvas, this); + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + } + + protected override void OnTransformParentChanged() + { + base.OnTransformParentChanged(); + + m_Canvas = null; + + if (!IsActive()) + return; + + CacheCanvas(); + GraphicRegistry.RegisterGraphicForCanvas(canvas, this); + SetAllDirty(); + } + + // 在hierachy里的深度,依次增加 + /// + /// Absolute depth of the graphic, used by rendering and events -- lowest to highest. + /// + public int depth { get { return canvasRenderer.absoluteDepth; } } + + /// + /// Transform gets cached for speed. + /// + public RectTransform rectTransform + { + get { return m_RectTransform ?? (m_RectTransform = GetComponent()); } + } + + public Canvas canvas + { + get + { + if (m_Canvas == null) + CacheCanvas(); + return m_Canvas; + } + } + + // 找到父节点中最近的canvas + private void CacheCanvas() + { + var list = ListPool.Get(); + // 找到所有父节点中所有canvas,从里到外 + gameObject.GetComponentsInParent(false, list); + if (list.Count > 0) + { + // Find the first active and enabled canvas. + for (int i = 0; i < list.Count; ++i) + { + if (list[i].isActiveAndEnabled) + { + m_Canvas = list[i]; + break; + } + } + } + else + m_Canvas = null; + ListPool.Release(list); + } + + /// + /// UI Renderer component. + /// + public CanvasRenderer canvasRenderer + { + get + { + if (m_CanvasRender == null) + m_CanvasRender = GetComponent(); + return m_CanvasRender; + } + } + + public virtual Material defaultMaterial + { + get { return defaultGraphicMaterial; } + } + + /// + /// Returns the material used by this Graphic. + /// + public virtual Material material + { + get + { + return (m_Material != null) ? m_Material : defaultMaterial; + } + set + { + if (m_Material == value) + return; + + m_Material = value; + SetMaterialDirty(); + } + } + + /// + /// 提交到CanvasRenderer用这个,要应用IMaterialModifier的修改结果 + /// + public virtual Material materialForRendering + { + get + { + // 在这里调用IMaterialModifier的修改 + var components = ListPool.Get(); + GetComponents(typeof(IMaterialModifier), components); + + var currentMat = material; + for (var i = 0; i < components.Count; i++) + currentMat = (components[i] as IMaterialModifier).GetModifiedMaterial(currentMat); + ListPool.Release(components); + return currentMat; + } + } + + /// + /// Returns the texture used to draw this Graphic. + /// + public virtual Texture mainTexture + { + get + { + return s_WhiteTexture; + } + } + + /// + /// Mark the Graphic and the canvas as having been changed. + /// + protected override void OnEnable() + { + base.OnEnable(); + CacheCanvas(); + GraphicRegistry.RegisterGraphicForCanvas(canvas, this); + +#if UNITY_EDITOR + GraphicRebuildTracker.TrackGraphic(this); +#endif + if (s_WhiteTexture == null) + s_WhiteTexture = Texture2D.whiteTexture; + + SetAllDirty(); + } + + /// + /// Clear references. + /// + protected override void OnDisable() + { +#if UNITY_EDITOR + GraphicRebuildTracker.UnTrackGraphic(this); +#endif + GraphicRegistry.UnregisterGraphicForCanvas(canvas, this); + CanvasUpdateRegistry.UnRegisterCanvasElementForRebuild(this); + + if (canvasRenderer != null) + canvasRenderer.Clear(); + + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + + base.OnDisable(); + } + + protected override void OnCanvasHierarchyChanged() + { + // Use m_Cavas so we dont auto call CacheCanvas + Canvas currentCanvas = m_Canvas; + + // Clear the cached canvas. Will be fetched below if active. + m_Canvas = null; + + if (!IsActive()) + return; + + CacheCanvas(); + + if (currentCanvas != m_Canvas) + { + GraphicRegistry.UnregisterGraphicForCanvas(currentCanvas, this); + + // Only register if we are active and enabled as OnCanvasHierarchyChanged can get called + // during object destruction and we dont want to register ourself and then become null. + if (IsActive()) + GraphicRegistry.RegisterGraphicForCanvas(canvas, this); + } + } + + // canvas重建 + public virtual void Rebuild(CanvasUpdate update) + { + if (canvasRenderer.cull) + return; + + switch (update) + { + case CanvasUpdate.PreRender: + if (m_VertsDirty) + { + UpdateGeometry(); + m_VertsDirty = false; + } + if (m_MaterialDirty) + { + UpdateMaterial(); + m_MaterialDirty = false; + } + break; + } + } + + public virtual void LayoutComplete() + {} + + public virtual void GraphicUpdateComplete() + {} + + /// + /// Update the renderer's material. + /// + protected virtual void UpdateMaterial() + { + if (!IsActive()) + return; + + canvasRenderer.materialCount = 1; + canvasRenderer.SetMaterial(materialForRendering, 0); + canvasRenderer.SetTexture(mainTexture); // 设置_MainTex,会覆盖材质上设置的_MainTex + } + + //c 顶点重建 + /// + /// Update the renderer's vertices. + /// + protected virtual void UpdateGeometry() + { + if (useLegacyMeshGeneration) + DoLegacyMeshGeneration(); + else + DoMeshGeneration(); + } + + // 顶点重建,生成mesh + private void DoMeshGeneration() + { + if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0) + OnPopulateMesh(s_VertexHelper); // 填充vertexHelper + else + s_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw. + + // 可以通过实现IMeshModifer修改mesh + var components = ListPool.Get(); + GetComponents(typeof(IMeshModifier), components); + + for (var i = 0; i < components.Count; i++) + ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper); + + ListPool.Release(components); + + s_VertexHelper.FillMesh(workerMesh); + + // 传入canvasRenderer作为mesh + canvasRenderer.SetMesh(workerMesh); + } + + private void DoLegacyMeshGeneration() + { + if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0) + { +#pragma warning disable 618 + OnPopulateMesh(workerMesh); +#pragma warning restore 618 + } + else + { + workerMesh.Clear(); + } + + // 自定义流程 + var components = ListPool.Get(); + GetComponents(typeof(IMeshModifier), components); + + for (var i = 0; i < components.Count; i++) + { +#pragma warning disable 618 + ((IMeshModifier)components[i]).ModifyMesh(workerMesh); +#pragma warning restore 618 + } + + ListPool.Release(components); + canvasRenderer.SetMesh(workerMesh); + } + + protected static Mesh workerMesh + { + get + { + if (s_Mesh == null) + { + s_Mesh = new Mesh(); + s_Mesh.name = "Shared UI Mesh"; + s_Mesh.hideFlags = HideFlags.HideAndDontSave; + } + return s_Mesh; + } + } + + [Obsolete("Use OnPopulateMesh instead.", true)] + protected virtual void OnFillVBO(System.Collections.Generic.List vbo) {} + + [Obsolete("Use OnPopulateMesh(VertexHelper vh) instead.", false)] + protected virtual void OnPopulateMesh(Mesh m) + { + OnPopulateMesh(s_VertexHelper); + s_VertexHelper.FillMesh(m); + } + + /// + /// Fill the vertex buffer data. + /// + protected virtual void OnPopulateMesh(VertexHelper vh) + { + var r = GetPixelAdjustedRect(); + var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height); + + Color32 color32 = color; + vh.Clear(); + vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f)); + vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f)); + vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f)); + vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f)); + + vh.AddTriangle(0, 1, 2); + vh.AddTriangle(2, 3, 0); + } + +#if UNITY_EDITOR + public virtual void OnRebuildRequested() + { + // when rebuild is requested we need to rebuild all the graphics / + // and associated components... The correct way to do this is by + // calling OnValidate... Because MB's don't have a common base class + // we do this via reflection. It's nasty and ugly... Editor only. + var mbs = gameObject.GetComponents(); + foreach (var mb in mbs) + { + if (mb == null) + continue; + var methodInfo = mb.GetType().GetMethod("OnValidate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + if (methodInfo != null) + methodInfo.Invoke(mb, null); + } + } + + protected override void Reset() + { + SetAllDirty(); + } + +#endif + + // Call from unity if animation properties have changed + + protected override void OnDidApplyAnimationProperties() + { + SetAllDirty(); + } + + /// + /// Make the Graphic have the native size of its content. + /// + public virtual void SetNativeSize() {} + public virtual bool Raycast(Vector2 sp, Camera eventCamera) + { + if (!isActiveAndEnabled) + return false; + + var t = transform; + var components = ListPool.Get(); + + bool ignoreParentGroups = false; + bool continueTraversal = true; + + while (t != null) + { + t.GetComponents(components); + for (var i = 0; i < components.Count; i++) + { + var canvas = components[i] as Canvas; + if (canvas != null && canvas.overrideSorting) + continueTraversal = false; + + // 如果实现了这个接口再进一步判断一下 + var filter = components[i] as ICanvasRaycastFilter; + + if (filter == null) + continue; + + var raycastValid = true; + + var group = components[i] as CanvasGroup; + if (group != null) + { + if (ignoreParentGroups == false && group.ignoreParentGroups) + { + ignoreParentGroups = true; + raycastValid = filter.IsRaycastLocationValid(sp, eventCamera); + } + else if (!ignoreParentGroups) + raycastValid = filter.IsRaycastLocationValid(sp, eventCamera); + } + else + { + raycastValid = filter.IsRaycastLocationValid(sp, eventCamera); + } + + if (!raycastValid) + { + ListPool.Release(components); + return false; + } + } + t = continueTraversal ? t.parent : null; + } + ListPool.Release(components); + return true; + } + +#if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + SetAllDirty(); + } + +#endif + + public Vector2 PixelAdjustPoint(Vector2 point) + { + if (!canvas || canvas.renderMode == RenderMode.WorldSpace || canvas.scaleFactor == 0.0f || !canvas.pixelPerfect) + return point; + else + { + return RectTransformUtility.PixelAdjustPoint(point, transform, canvas); + } + } + + public Rect GetPixelAdjustedRect() + { + if (!canvas || canvas.renderMode == RenderMode.WorldSpace || canvas.scaleFactor == 0.0f || !canvas.pixelPerfect) + return rectTransform.rect; + else + return RectTransformUtility.PixelAdjustRect(rectTransform, canvas); + } + + public virtual void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha) + { + CrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha, true); + } + + public virtual void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha, bool useRGB) + { + if (canvasRenderer == null || (!useRGB && !useAlpha)) + return; + + Color currentColor = canvasRenderer.GetColor(); + if (currentColor.Equals(targetColor)) + { + m_ColorTweenRunner.StopTween(); + return; + } + + ColorTween.ColorTweenMode mode = (useRGB && useAlpha ? + ColorTween.ColorTweenMode.All : + (useRGB ? ColorTween.ColorTweenMode.RGB : ColorTween.ColorTweenMode.Alpha)); + + var colorTween = new ColorTween {duration = duration, startColor = canvasRenderer.GetColor(), targetColor = targetColor}; + colorTween.AddOnChangedCallback(canvasRenderer.SetColor); + colorTween.ignoreTimeScale = ignoreTimeScale; + colorTween.tweenMode = mode; + m_ColorTweenRunner.StartTween(colorTween); + } + + static private Color CreateColorFromAlpha(float alpha) + { + var alphaColor = Color.black; + alphaColor.a = alpha; + return alphaColor; + } + + public virtual void CrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale) + { + CrossFadeColor(CreateColorFromAlpha(alpha), duration, ignoreTimeScale, true, false); + } + + public void RegisterDirtyLayoutCallback(UnityAction action) + { + m_OnDirtyLayoutCallback += action; + } + + public void UnregisterDirtyLayoutCallback(UnityAction action) + { + m_OnDirtyLayoutCallback -= action; + } + + public void RegisterDirtyVerticesCallback(UnityAction action) + { + m_OnDirtyVertsCallback += action; + } + + public void UnregisterDirtyVerticesCallback(UnityAction action) + { + m_OnDirtyVertsCallback -= action; + } + + public void RegisterDirtyMaterialCallback(UnityAction action) + { + m_OnDirtyMaterialCallback += action; + } + + public void UnregisterDirtyMaterialCallback(UnityAction action) + { + m_OnDirtyMaterialCallback -= action; + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta new file mode 100644 index 0000000..e02d697 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Graphic.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3acb46ac7ba14ff4e938138943716b11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs new file mode 100644 index 0000000..303689a --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs @@ -0,0 +1,290 @@ +using System; +using System.Collections.Generic; +using System.Text; +using UnityEngine.EventSystems; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + [AddComponentMenu("Event/Graphic Raycaster")] + [RequireComponent(typeof(Canvas))] + public class GraphicRaycaster : BaseRaycaster + { + protected const int kNoEventMaskSet = -1; + public enum BlockingObjects + { + None = 0, + TwoD = 1, + ThreeD = 2, + All = 3, + } + + public override int sortOrderPriority + { + get + { + // We need to return the sorting order here as distance will all be 0 for overlay. + if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) + return canvas.sortingOrder; + + return base.sortOrderPriority; + } + } + + public override int renderOrderPriority + { + get + { + // We need to return the sorting order here as distance will all be 0 for overlay. + if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) + return canvas.rootCanvas.renderOrder; + + return base.renderOrderPriority; + } + } + + [FormerlySerializedAs("ignoreReversedGraphics")] + [SerializeField] + private bool m_IgnoreReversedGraphics = true; + [FormerlySerializedAs("blockingObjects")] + [SerializeField] + private BlockingObjects m_BlockingObjects = BlockingObjects.None; + + public bool ignoreReversedGraphics { get {return m_IgnoreReversedGraphics; } set { m_IgnoreReversedGraphics = value; } } + public BlockingObjects blockingObjects { get {return m_BlockingObjects; } set { m_BlockingObjects = value; } } + + [SerializeField] + protected LayerMask m_BlockingMask = kNoEventMaskSet; + + private Canvas m_Canvas; + + protected GraphicRaycaster() + {} + + private Canvas canvas + { + get + { + if (m_Canvas != null) + return m_Canvas; + + m_Canvas = GetComponent(); + return m_Canvas; + } + } + + [NonSerialized] private List m_RaycastResults = new List(); + public override void Raycast(PointerEventData eventData, List resultAppendList) + { + if (canvas == null) + return; + + // 拿到canvas下的所有graphic + var canvasGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas); + if (canvasGraphics == null || canvasGraphics.Count == 0) + return; + + int displayIndex; + var currentEventCamera = eventCamera; // Propery can call Camera.main, so cache the reference + + if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || currentEventCamera == null) + displayIndex = canvas.targetDisplay; + else + displayIndex = currentEventCamera.targetDisplay; + + var eventPosition = Display.RelativeMouseAt(eventData.position); + if (eventPosition != Vector3.zero) + { + // We support multiple display and display identification based on event position. + + int eventDisplayIndex = (int)eventPosition.z; + + // Discard events that are not part of this display so the user does not interact with multiple displays at once. + if (eventDisplayIndex != displayIndex) + return; + } + else + { + // The multiple display system is not supported on all platforms, when it is not supported the returned position + // will be all zeros so when the returned index is 0 we will default to the event data to be safe. + eventPosition = eventData.position; + + // We dont really know in which display the event occured. We will process the event assuming it occured in our display. + } + + // Convert to view space + Vector2 pos; + if (currentEventCamera == null) + { + // Multiple display support only when not the main display. For display 0 the reported + // resolution is always the desktops resolution since its part of the display API, + // so we use the standard none multiple display method. (case 741751) + float w = Screen.width; + float h = Screen.height; + if (displayIndex > 0 && displayIndex < Display.displays.Length) + { + w = Display.displays[displayIndex].systemWidth; + h = Display.displays[displayIndex].systemHeight; + } + pos = new Vector2(eventPosition.x / w, eventPosition.y / h); + } + else + pos = currentEventCamera.ScreenToViewportPoint(eventPosition); + + // If it's outside the camera's viewport, do nothing + if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f) + return; + + float hitDistance = float.MaxValue; + + Ray ray = new Ray(); + + if (currentEventCamera != null) + ray = currentEventCamera.ScreenPointToRay(eventPosition); + + if (canvas.renderMode != RenderMode.ScreenSpaceOverlay && blockingObjects != BlockingObjects.None) + { + float distanceToClipPlane = 100.0f; + + if (currentEventCamera != null) + { + float projectionDirection = ray.direction.z; + distanceToClipPlane = Mathf.Approximately(0.0f, projectionDirection) + ? Mathf.Infinity + : Mathf.Abs((currentEventCamera.farClipPlane - currentEventCamera.nearClipPlane) / projectionDirection); + } + + if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All) + { + if (ReflectionMethodsCache.Singleton.raycast3D != null) + { + var hits = ReflectionMethodsCache.Singleton.raycast3DAll(ray, distanceToClipPlane, (int)m_BlockingMask); + if (hits.Length > 0) + hitDistance = hits[0].distance; + } + } + + if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All) + { + if (ReflectionMethodsCache.Singleton.raycast2D != null) + { + var hits = ReflectionMethodsCache.Singleton.getRayIntersectionAll(ray, distanceToClipPlane, (int)m_BlockingMask); + if (hits.Length > 0) + hitDistance = hits[0].distance; + } + } + } + + m_RaycastResults.Clear(); + Raycast(canvas, currentEventCamera, eventPosition, canvasGraphics, m_RaycastResults); + + int totalCount = m_RaycastResults.Count; + for (var index = 0; index < totalCount; index++) + { + var go = m_RaycastResults[index].gameObject; + bool appendGraphic = true; + + if (ignoreReversedGraphics) + { + if (currentEventCamera == null) + { + // If we dont have a camera we know that we should always be facing forward + var dir = go.transform.rotation * Vector3.forward; + appendGraphic = Vector3.Dot(Vector3.forward, dir) > 0; + } + else + { + // If we have a camera compare the direction against the cameras forward. + var cameraFoward = currentEventCamera.transform.rotation * Vector3.forward; + var dir = go.transform.rotation * Vector3.forward; + appendGraphic = Vector3.Dot(cameraFoward, dir) > 0; + } + } + + if (appendGraphic) + { + float distance = 0; + + if (currentEventCamera == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay) + distance = 0; + else + { + Transform trans = go.transform; + Vector3 transForward = trans.forward; + // http://geomalgorithms.com/a06-_intersect-2.html + distance = (Vector3.Dot(transForward, trans.position - currentEventCamera.transform.position) / Vector3.Dot(transForward, ray.direction)); + + // Check to see if the go is behind the camera. + if (distance < 0) + continue; + } + + if (distance >= hitDistance) + continue; + + var castResult = new RaycastResult + { + gameObject = go, + module = this, + distance = distance, + screenPosition = eventPosition, + index = resultAppendList.Count, + depth = m_RaycastResults[index].depth, + sortingLayer = canvas.sortingLayerID, + sortingOrder = canvas.sortingOrder + }; + resultAppendList.Add(castResult); + } + } + } + + public override Camera eventCamera + { + get + { + if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || (canvas.renderMode == RenderMode.ScreenSpaceCamera && canvas.worldCamera == null)) + return null; + + return canvas.worldCamera != null ? canvas.worldCamera : Camera.main; + } + } + + // + /// + /// Perform a raycast into the screen and collect all graphics underneath it. + /// + [NonSerialized] static readonly List s_SortedGraphics = new List(); + private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, IList foundGraphics, List results) + { + // Debug.Log("ttt" + pointerPoision + ":::" + camera); + // Necessary for the event system + int totalCount = foundGraphics.Count; + for (int i = 0; i < totalCount; ++i) + { + Graphic graphic = foundGraphics[i]; + + // -1 means it hasn't been processed by the canvas, which means it isn't actually drawn + if (graphic.depth == -1 || !graphic.raycastTarget || graphic.canvasRenderer.cull) + continue; + + if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera)) + continue; + + if (graphic.Raycast(pointerPosition, eventCamera)) + { + s_SortedGraphics.Add(graphic); + } + } + + // 从高到低,所以会以深度优先。越深的越先响应。 + s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth)); + // StringBuilder cast = new StringBuilder(); + totalCount = s_SortedGraphics.Count; + for (int i = 0; i < totalCount; ++i) + results.Add(s_SortedGraphics[i]); + // Debug.Log (cast.ToString()); + + s_SortedGraphics.Clear(); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta new file mode 100644 index 0000000..d51fee9 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRaycaster.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0dc7198a94080b64e9e51e6f934b3e35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs new file mode 100644 index 0000000..c081269 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs @@ -0,0 +1,38 @@ +#if UNITY_EDITOR +using System.Collections.Generic; +using UnityEngine.UI.Collections; + +namespace UnityEngine.UI +{ + public static class GraphicRebuildTracker + { + static IndexedSet m_Tracked = new IndexedSet(); + static bool s_Initialized; + + public static void TrackGraphic(Graphic g) + { + if (!s_Initialized) + { + CanvasRenderer.onRequestRebuild += OnRebuildRequested; + s_Initialized = true; + } + + m_Tracked.AddUnique(g); + } + + public static void UnTrackGraphic(Graphic g) + { + m_Tracked.Remove(g); + } + + static void OnRebuildRequested() + { + StencilMaterial.ClearAll(); + for (int i = 0; i < m_Tracked.Count; i++) + { + m_Tracked[i].OnRebuildRequested(); + } + } + } +} +#endif // if UNITY_EDITOR diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta new file mode 100644 index 0000000..d0fff87 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRebuildTracker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40f1f16390b7d7842b9e0c5df6baa9d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs new file mode 100644 index 0000000..0642792 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using UnityEngine.UI.Collections; + +namespace UnityEngine.UI +{ + // 游戏中只有一份单例 + public class GraphicRegistry + { + private static GraphicRegistry s_Instance; + + // 按Canvas分类统计Graphic + private readonly Dictionary> m_Graphics = new Dictionary>(); + + protected GraphicRegistry() + { + // This is needed for AOT on IOS. Without it the compile doesn't get the definition of the Dictionarys +#pragma warning disable 168 + Dictionary emptyGraphicDic; + Dictionary emptyElementDic; +#pragma warning restore 168 + } + + public static GraphicRegistry instance + { + get + { + if (s_Instance == null) + s_Instance = new GraphicRegistry(); + return s_Instance; + } + } + + public static void RegisterGraphicForCanvas(Canvas c, Graphic graphic) + { + if (c == null) + return; + + IndexedSet graphics; + instance.m_Graphics.TryGetValue(c, out graphics); + + if (graphics != null) + { + graphics.AddUnique(graphic); + return; + } + + // Dont need to AddUnique as we know its the only item in the list + graphics = new IndexedSet(); + graphics.Add(graphic); + instance.m_Graphics.Add(c, graphics); + } + + public static void UnregisterGraphicForCanvas(Canvas c, Graphic graphic) + { + if (c == null) + return; + + IndexedSet graphics; + if (instance.m_Graphics.TryGetValue(c, out graphics)) + { + graphics.Remove(graphic); + + if (graphics.Count == 0) + instance.m_Graphics.Remove(c); + } + } + + private static readonly List s_EmptyList = new List(); + public static IList GetGraphicsForCanvas(Canvas canvas) + { + IndexedSet graphics; + if (instance.m_Graphics.TryGetValue(canvas, out graphics)) + return graphics; + + return s_EmptyList; + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta new file mode 100644 index 0000000..bc0ed05 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/GraphicRegistry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0a078c41319d0f4ab759c3ad44fd733 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs new file mode 100644 index 0000000..f2becbb --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs @@ -0,0 +1,10 @@ +using System; + +namespace UnityEngine.UI +{ + [Obsolete("Not supported anymore")] + interface IGraphicEnabledDisabled + { + void OnSiblingGraphicEnabledDisabled(); + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta new file mode 100644 index 0000000..24c8266 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/IGraphicEnabledDisabled.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6892dbec884b7b4482fe7cdb11bc565 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs new file mode 100644 index 0000000..65e0cfd --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs @@ -0,0 +1,1171 @@ +using System; +using System.Collections.Generic; +using System.Text; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + /// + /// Image is a textured element in the UI hierarchy. + /// + + [AddComponentMenu("UI/Image", 11)] + public class Image : MaskableGraphic, ISerializationCallbackReceiver, ILayoutElement, ICanvasRaycastFilter + { + public enum Type + { + Simple, + Sliced, + Tiled, + Filled + } + + public enum FillMethod + { + Horizontal, + Vertical, + Radial90, + Radial180, + Radial360, + } + + public enum OriginHorizontal + { + Left, + Right, + } + + public enum OriginVertical + { + Bottom, + Top, + } + + public enum Origin90 + { + BottomLeft, + TopLeft, + TopRight, + BottomRight, + } + + public enum Origin180 + { + Bottom, + Left, + Top, + Right, + } + + public enum Origin360 + { + Bottom, + Right, + Top, + Left, + } + + static protected Material s_ETC1DefaultUI = null; + + [FormerlySerializedAs("m_Frame")] + [SerializeField] private Sprite m_Sprite; + public Sprite sprite { get { return m_Sprite; } set { if (SetPropertyUtility.SetClass(ref m_Sprite, value)) SetAllDirty(); } } + + [NonSerialized] + private Sprite m_OverrideSprite; + public Sprite overrideSprite { get { return activeSprite; } set { if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value)) SetAllDirty(); } } + + private Sprite activeSprite { get { return m_OverrideSprite != null ? m_OverrideSprite : sprite; } } + + /// How the Image is drawn. + [SerializeField] private Type m_Type = Type.Simple; + public Type type { get { return m_Type; } set { if (SetPropertyUtility.SetStruct(ref m_Type, value)) SetVerticesDirty(); } } + + [SerializeField] private bool m_PreserveAspect = false; + public bool preserveAspect { get { return m_PreserveAspect; } set { if (SetPropertyUtility.SetStruct(ref m_PreserveAspect, value)) SetVerticesDirty(); } } + + [SerializeField] private bool m_FillCenter = true; + public bool fillCenter { get { return m_FillCenter; } set { if (SetPropertyUtility.SetStruct(ref m_FillCenter, value)) SetVerticesDirty(); } } + + /// Filling method for filled sprites. + [SerializeField] private FillMethod m_FillMethod = FillMethod.Radial360; + public FillMethod fillMethod { get { return m_FillMethod; } set { if (SetPropertyUtility.SetStruct(ref m_FillMethod, value)) { SetVerticesDirty(); m_FillOrigin = 0; } } } + + /// Amount of the Image shown. 0-1 range with 0 being nothing shown, and 1 being the full Image. + [Range(0, 1)] + [SerializeField] private float m_FillAmount = 1.0f; + public float fillAmount { get { return m_FillAmount; } set { if (SetPropertyUtility.SetStruct(ref m_FillAmount, Mathf.Clamp01(value))) SetVerticesDirty(); } } + + /// Whether the Image should be filled clockwise (true) or counter-clockwise (false). + [SerializeField] private bool m_FillClockwise = true; + public bool fillClockwise { get { return m_FillClockwise; } set { if (SetPropertyUtility.SetStruct(ref m_FillClockwise, value)) SetVerticesDirty(); } } + + /// Controls the origin point of the Fill process. Value means different things with each fill method. + [SerializeField] private int m_FillOrigin; + public int fillOrigin { get { return m_FillOrigin; } set { if (SetPropertyUtility.SetStruct(ref m_FillOrigin, value)) SetVerticesDirty(); } } + + // Not serialized until we support read-enabled sprites better. + private float m_AlphaHitTestMinimumThreshold = 0; + + [Obsolete("eventAlphaThreshold has been deprecated. Use eventMinimumAlphaThreshold instead (UnityUpgradable) -> alphaHitTestMinimumThreshold")] + public float eventAlphaThreshold { get { return 1 - alphaHitTestMinimumThreshold; } set { alphaHitTestMinimumThreshold = 1 - value; } } + public float alphaHitTestMinimumThreshold { get { return m_AlphaHitTestMinimumThreshold; } set { m_AlphaHitTestMinimumThreshold = value; } } + + protected Image() + { + useLegacyMeshGeneration = false; + } + + /// + /// Default material used to draw everything if no explicit material was specified. + /// + + static public Material defaultETC1GraphicMaterial + { + get + { + if (s_ETC1DefaultUI == null) + s_ETC1DefaultUI = Canvas.GetETC1SupportedCanvasMaterial(); + return s_ETC1DefaultUI; + } + } + + /// + /// Image's texture comes from the UnityEngine.Image. + /// + public override Texture mainTexture + { + get + { + if (activeSprite == null) + { + if (material != null && material.mainTexture != null) + { + return material.mainTexture; + } + return s_WhiteTexture; + } + + return activeSprite.texture; + } + } + + /// + /// Whether the Image has a border to work with. + /// + + public bool hasBorder + { + get + { + if (activeSprite != null) + { + Vector4 v = activeSprite.border; + return v.sqrMagnitude > 0f; + } + return false; + } + } + + public float pixelsPerUnit + { + get + { + float spritePixelsPerUnit = 100; + if (activeSprite) + spritePixelsPerUnit = activeSprite.pixelsPerUnit; + + float referencePixelsPerUnit = 100; + if (canvas) + referencePixelsPerUnit = canvas.referencePixelsPerUnit; + + return spritePixelsPerUnit / referencePixelsPerUnit; + } + } + + public override Material material + { + get + { + if (m_Material != null) + return m_Material; + + if (activeSprite && activeSprite.associatedAlphaSplitTexture != null) + return defaultETC1GraphicMaterial; + + return defaultMaterial; + } + + set + { + base.material = value; + } + } + + public virtual void OnBeforeSerialize() + { + //Debug.Log("OnBeforeSerialize"); + } + + // 序列化之后,即修改了序列化参数之后。校正一下结果 + public virtual void OnAfterDeserialize() + { + if (m_FillOrigin < 0) + m_FillOrigin = 0; + else if (m_FillMethod == FillMethod.Horizontal && m_FillOrigin > 1) + m_FillOrigin = 0; + else if (m_FillMethod == FillMethod.Vertical && m_FillOrigin > 1) + m_FillOrigin = 0; + else if (m_FillOrigin > 3) + m_FillOrigin = 0; + + m_FillAmount = Mathf.Clamp(m_FillAmount, 0f, 1f); + } + + /// Image's dimensions used for drawing. X = left, Y = bottom, Z = right, W = top. + private Vector4 GetDrawingDimensions(bool shouldPreserveAspect) + { + var padding = activeSprite == null ? Vector4.zero : Sprites.DataUtility.GetPadding(activeSprite); + var size = activeSprite == null ? Vector2.zero : new Vector2(activeSprite.rect.width, activeSprite.rect.height); + + Rect r = GetPixelAdjustedRect(); + // Debug.Log(string.Format("r:{2}, size:{0}, padding:{1}", size, padding, r)); + + int spriteW = Mathf.RoundToInt(size.x); + int spriteH = Mathf.RoundToInt(size.y); + + var v = new Vector4( + padding.x / spriteW, + padding.y / spriteH, + (spriteW - padding.z) / spriteW, + (spriteH - padding.w) / spriteH); + + if (shouldPreserveAspect && size.sqrMagnitude > 0.0f) + { + var spriteRatio = size.x / size.y; + var rectRatio = r.width / r.height; + + if (spriteRatio > rectRatio) + { + var oldHeight = r.height; + r.height = r.width * (1.0f / spriteRatio); + r.y += (oldHeight - r.height) * rectTransform.pivot.y; + } + else + { + var oldWidth = r.width; + r.width = r.height * spriteRatio; + r.x += (oldWidth - r.width) * rectTransform.pivot.x; + } + } + + v = new Vector4( + r.x + r.width * v.x, + r.y + r.height * v.y, + r.x + r.width * v.z, + r.y + r.height * v.w + ); + + return v; + } + + public override void SetNativeSize() + { + if (activeSprite != null) + { + float w = activeSprite.rect.width / pixelsPerUnit; + float h = activeSprite.rect.height / pixelsPerUnit; + rectTransform.anchorMax = rectTransform.anchorMin; + rectTransform.sizeDelta = new Vector2(w, h); + SetAllDirty(); + } + } + + /// + /// Update the UI renderer mesh. + /// + protected override void OnPopulateMesh(VertexHelper toFill) + { + if (activeSprite == null) + { + base.OnPopulateMesh(toFill); + return; + } + + switch (type) + { + case Type.Simple: + GenerateSimpleSprite(toFill, m_PreserveAspect); + break; + case Type.Sliced: + GenerateSlicedSprite(toFill); + break; + case Type.Tiled: + GenerateTiledSprite(toFill); + break; + case Type.Filled: + GenerateFilledSprite(toFill, m_PreserveAspect); + break; + } + } + + /// + /// Update the renderer's material. + /// + + protected override void UpdateMaterial() + { + base.UpdateMaterial(); + + // check if this sprite has an associated alpha texture (generated when splitting RGBA = RGB + A as two textures without alpha) + + if (activeSprite == null) + { + canvasRenderer.SetAlphaTexture(null); + return; + } + + //如果是ETC压缩格式,会生成一份alphaTex只保存透明度信息,不在_MainTex里 + Texture2D alphaTex = activeSprite.associatedAlphaSplitTexture; + + if (alphaTex != null) + { + canvasRenderer.SetAlphaTexture(alphaTex); // _AlphaTex + } + } + + /// + /// Generate vertices for a simple Image. + /// + void GenerateSimpleSprite(VertexHelper vh, bool lPreserveAspect) + { + Vector4 v = GetDrawingDimensions(lPreserveAspect); + var uv = (activeSprite != null) ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero; + + var color32 = color; + vh.Clear(); + vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(uv.x, uv.y)); + vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(uv.x, uv.w)); + vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(uv.z, uv.w)); + vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(uv.z, uv.y)); + + vh.AddTriangle(0, 1, 2); + vh.AddTriangle(2, 3, 0); + } + + /// + /// Generate vertices for a 9-sliced Image. + /// + + static readonly Vector2[] s_VertScratch = new Vector2[4]; + static readonly Vector2[] s_UVScratch = new Vector2[4]; + + private void GenerateSlicedSprite(VertexHelper toFill) + { + if (!hasBorder) + { + GenerateSimpleSprite(toFill, false); + return; + } + + Vector4 outer, inner, padding, border; + + if (activeSprite != null) + { + outer = Sprites.DataUtility.GetOuterUV(activeSprite); + inner = Sprites.DataUtility.GetInnerUV(activeSprite); + padding = Sprites.DataUtility.GetPadding(activeSprite); + border = activeSprite.border; + } + else + { + outer = Vector4.zero; + inner = Vector4.zero; + padding = Vector4.zero; + border = Vector4.zero; + } + + Rect rect = GetPixelAdjustedRect(); + Vector4 adjustedBorders = GetAdjustedBorders(border / pixelsPerUnit, rect); + padding = padding / pixelsPerUnit; + + s_VertScratch[0] = new Vector2(padding.x, padding.y); + s_VertScratch[3] = new Vector2(rect.width - padding.z, rect.height - padding.w); + + s_VertScratch[1].x = adjustedBorders.x; + s_VertScratch[1].y = adjustedBorders.y; + + s_VertScratch[2].x = rect.width - adjustedBorders.z; + s_VertScratch[2].y = rect.height - adjustedBorders.w; + + for (int i = 0; i < 4; ++i) + { + s_VertScratch[i].x += rect.x; + s_VertScratch[i].y += rect.y; + } + + s_UVScratch[0] = new Vector2(outer.x, outer.y); + s_UVScratch[1] = new Vector2(inner.x, inner.y); + s_UVScratch[2] = new Vector2(inner.z, inner.w); + s_UVScratch[3] = new Vector2(outer.z, outer.w); + + toFill.Clear(); + + for (int x = 0; x < 3; ++x) + { + int x2 = x + 1; + + for (int y = 0; y < 3; ++y) + { + if (!m_FillCenter && x == 1 && y == 1) + continue; + + int y2 = y + 1; + + + AddQuad(toFill, + new Vector2(s_VertScratch[x].x, s_VertScratch[y].y), + new Vector2(s_VertScratch[x2].x, s_VertScratch[y2].y), + color, + new Vector2(s_UVScratch[x].x, s_UVScratch[y].y), + new Vector2(s_UVScratch[x2].x, s_UVScratch[y2].y)); + } + } + } + + /// + /// Generate vertices for a tiled Image. + /// + + void GenerateTiledSprite(VertexHelper toFill) + { + Vector4 outer, inner, border; + Vector2 spriteSize; + + if (activeSprite != null) + { + outer = Sprites.DataUtility.GetOuterUV(activeSprite); + inner = Sprites.DataUtility.GetInnerUV(activeSprite); + border = activeSprite.border; + spriteSize = activeSprite.rect.size; + } + else + { + outer = Vector4.zero; + inner = Vector4.zero; + border = Vector4.zero; + spriteSize = Vector2.one * 100; + } + + Rect rect = GetPixelAdjustedRect(); + float tileWidth = (spriteSize.x - border.x - border.z) / pixelsPerUnit; + float tileHeight = (spriteSize.y - border.y - border.w) / pixelsPerUnit; + border = GetAdjustedBorders(border / pixelsPerUnit, rect); + + var uvMin = new Vector2(inner.x, inner.y); + var uvMax = new Vector2(inner.z, inner.w); + + // Min to max max range for tiled region in coordinates relative to lower left corner. + float xMin = border.x; + float xMax = rect.width - border.z; + float yMin = border.y; + float yMax = rect.height - border.w; + + toFill.Clear(); + var clipped = uvMax; + + // if either width is zero we cant tile so just assume it was the full width. + if (tileWidth <= 0) + tileWidth = xMax - xMin; + + if (tileHeight <= 0) + tileHeight = yMax - yMin; + + if (activeSprite != null && (hasBorder || activeSprite.packed || activeSprite.texture.wrapMode != TextureWrapMode.Repeat)) + { + // Sprite has border, or is not in repeat mode, or cannot be repeated because of packing. + // We cannot use texture tiling so we will generate a mesh of quads to tile the texture. + + // Evaluate how many vertices we will generate. Limit this number to something sane, + // especially since meshes can not have more than 65000 vertices. + + long nTilesW = 0; + long nTilesH = 0; + if (m_FillCenter) + { + nTilesW = (long)Math.Ceiling((xMax - xMin) / tileWidth); + nTilesH = (long)Math.Ceiling((yMax - yMin) / tileHeight); + + double nVertices = 0; + if (hasBorder) + { + nVertices = (nTilesW + 2.0) * (nTilesH + 2.0) * 4.0; // 4 vertices per tile + } + else + { + nVertices = nTilesW * nTilesH * 4.0; // 4 vertices per tile + } + + if (nVertices > 65000.0) + { + Debug.LogError("Too many sprite tiles on Image \"" + name + "\". The tile size will be increased. To remove the limit on the number of tiles, convert the Sprite to an Advanced texture, remove the borders, clear the Packing tag and set the Wrap mode to Repeat.", this); + + double maxTiles = 65000.0 / 4.0; // Max number of vertices is 65000; 4 vertices per tile. + double imageRatio; + if (hasBorder) + { + imageRatio = (nTilesW + 2.0) / (nTilesH + 2.0); + } + else + { + imageRatio = (double)nTilesW / nTilesH; + } + + double targetTilesW = Math.Sqrt(maxTiles / imageRatio); + double targetTilesH = targetTilesW * imageRatio; + if (hasBorder) + { + targetTilesW -= 2; + targetTilesH -= 2; + } + + nTilesW = (long)Math.Floor(targetTilesW); + nTilesH = (long)Math.Floor(targetTilesH); + tileWidth = (xMax - xMin) / nTilesW; + tileHeight = (yMax - yMin) / nTilesH; + } + } + else + { + if (hasBorder) + { + // Texture on the border is repeated only in one direction. + nTilesW = (long)Math.Ceiling((xMax - xMin) / tileWidth); + nTilesH = (long)Math.Ceiling((yMax - yMin) / tileHeight); + double nVertices = (nTilesH + nTilesW + 2.0 /*corners*/) * 2.0 /*sides*/ * 4.0 /*vertices per tile*/; + if (nVertices > 65000.0) + { + Debug.LogError("Too many sprite tiles on Image \"" + name + "\". The tile size will be increased. To remove the limit on the number of tiles, convert the Sprite to an Advanced texture, remove the borders, clear the Packing tag and set the Wrap mode to Repeat.", this); + + double maxTiles = 65000.0 / 4.0; // Max number of vertices is 65000; 4 vertices per tile. + double imageRatio = (double)nTilesW / nTilesH; + double targetTilesW = (maxTiles - 4 /*corners*/) / (2 * (1.0 + imageRatio)); + double targetTilesH = targetTilesW * imageRatio; + + nTilesW = (long)Math.Floor(targetTilesW); + nTilesH = (long)Math.Floor(targetTilesH); + tileWidth = (xMax - xMin) / nTilesW; + tileHeight = (yMax - yMin) / nTilesH; + } + } + else + { + nTilesH = nTilesW = 0; + } + } + + if (m_FillCenter) + { + // TODO: we could share vertices between quads. If vertex sharing is implemented. update the computation for the number of vertices accordingly. + for (long j = 0; j < nTilesH; j++) + { + float y1 = yMin + j * tileHeight; + float y2 = yMin + (j + 1) * tileHeight; + if (y2 > yMax) + { + clipped.y = uvMin.y + (uvMax.y - uvMin.y) * (yMax - y1) / (y2 - y1); + y2 = yMax; + } + clipped.x = uvMax.x; + for (long i = 0; i < nTilesW; i++) + { + float x1 = xMin + i * tileWidth; + float x2 = xMin + (i + 1) * tileWidth; + if (x2 > xMax) + { + clipped.x = uvMin.x + (uvMax.x - uvMin.x) * (xMax - x1) / (x2 - x1); + x2 = xMax; + } + AddQuad(toFill, new Vector2(x1, y1) + rect.position, new Vector2(x2, y2) + rect.position, color, uvMin, clipped); + } + } + } + if (hasBorder) + { + clipped = uvMax; + for (long j = 0; j < nTilesH; j++) + { + float y1 = yMin + j * tileHeight; + float y2 = yMin + (j + 1) * tileHeight; + if (y2 > yMax) + { + clipped.y = uvMin.y + (uvMax.y - uvMin.y) * (yMax - y1) / (y2 - y1); + y2 = yMax; + } + AddQuad(toFill, + new Vector2(0, y1) + rect.position, + new Vector2(xMin, y2) + rect.position, + color, + new Vector2(outer.x, uvMin.y), + new Vector2(uvMin.x, clipped.y)); + AddQuad(toFill, + new Vector2(xMax, y1) + rect.position, + new Vector2(rect.width, y2) + rect.position, + color, + new Vector2(uvMax.x, uvMin.y), + new Vector2(outer.z, clipped.y)); + } + + // Bottom and top tiled border + clipped = uvMax; + for (long i = 0; i < nTilesW; i++) + { + float x1 = xMin + i * tileWidth; + float x2 = xMin + (i + 1) * tileWidth; + if (x2 > xMax) + { + clipped.x = uvMin.x + (uvMax.x - uvMin.x) * (xMax - x1) / (x2 - x1); + x2 = xMax; + } + AddQuad(toFill, + new Vector2(x1, 0) + rect.position, + new Vector2(x2, yMin) + rect.position, + color, + new Vector2(uvMin.x, outer.y), + new Vector2(clipped.x, uvMin.y)); + AddQuad(toFill, + new Vector2(x1, yMax) + rect.position, + new Vector2(x2, rect.height) + rect.position, + color, + new Vector2(uvMin.x, uvMax.y), + new Vector2(clipped.x, outer.w)); + } + + // Corners + AddQuad(toFill, + new Vector2(0, 0) + rect.position, + new Vector2(xMin, yMin) + rect.position, + color, + new Vector2(outer.x, outer.y), + new Vector2(uvMin.x, uvMin.y)); + AddQuad(toFill, + new Vector2(xMax, 0) + rect.position, + new Vector2(rect.width, yMin) + rect.position, + color, + new Vector2(uvMax.x, outer.y), + new Vector2(outer.z, uvMin.y)); + AddQuad(toFill, + new Vector2(0, yMax) + rect.position, + new Vector2(xMin, rect.height) + rect.position, + color, + new Vector2(outer.x, uvMax.y), + new Vector2(uvMin.x, outer.w)); + AddQuad(toFill, + new Vector2(xMax, yMax) + rect.position, + new Vector2(rect.width, rect.height) + rect.position, + color, + new Vector2(uvMax.x, uvMax.y), + new Vector2(outer.z, outer.w)); + } + } + else + { + // Texture has no border, is in repeat mode and not packed. Use texture tiling. + Vector2 uvScale = new Vector2((xMax - xMin) / tileWidth, (yMax - yMin) / tileHeight); + + if (m_FillCenter) + { + AddQuad(toFill, new Vector2(xMin, yMin) + rect.position, new Vector2(xMax, yMax) + rect.position, color, Vector2.Scale(uvMin, uvScale), Vector2.Scale(uvMax, uvScale)); + } + } + } + + static void AddQuad(VertexHelper vertexHelper, Vector3[] quadPositions, Color32 color, Vector3[] quadUVs) + { + int startIndex = vertexHelper.currentVertCount; + + for (int i = 0; i < 4; ++i) + vertexHelper.AddVert(quadPositions[i], color, quadUVs[i]); + + vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2); + vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex); + } + + static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax) + { + int startIndex = vertexHelper.currentVertCount; + + vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y)); + vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y)); + vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y)); + vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y)); + + vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2); + vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex); + } + + private Vector4 GetAdjustedBorders(Vector4 border, Rect adjustedRect) + { + Rect originalRect = rectTransform.rect; + + for (int axis = 0; axis <= 1; axis++) + { + float borderScaleRatio; + + // The adjusted rect (adjusted for pixel correctness) + // may be slightly larger than the original rect. + // Adjust the border to match the adjustedRect to avoid + // small gaps between borders (case 833201). + if (originalRect.size[axis] != 0) + { + borderScaleRatio = adjustedRect.size[axis] / originalRect.size[axis]; + border[axis] *= borderScaleRatio; + border[axis + 2] *= borderScaleRatio; + } + + // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size. + // In order to avoid artefacts with overlapping borders, we scale the borders down to fit. + float combinedBorders = border[axis] + border[axis + 2]; + if (adjustedRect.size[axis] < combinedBorders && combinedBorders != 0) + { + borderScaleRatio = adjustedRect.size[axis] / combinedBorders; + border[axis] *= borderScaleRatio; + border[axis + 2] *= borderScaleRatio; + } + } + return border; + } + + /// + /// Generate vertices for a filled Image. + /// + + static readonly Vector3[] s_Xy = new Vector3[4]; + static readonly Vector3[] s_Uv = new Vector3[4]; + void GenerateFilledSprite(VertexHelper toFill, bool preserveAspect) + { + toFill.Clear(); + + if (m_FillAmount < 0.001f) + return; + + Vector4 v = GetDrawingDimensions(preserveAspect); + Vector4 outer = activeSprite != null ? Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero; + UIVertex uiv = UIVertex.simpleVert; + uiv.color = color; + + float tx0 = outer.x; + float ty0 = outer.y; + float tx1 = outer.z; + float ty1 = outer.w; + + // Horizontal and vertical filled sprites are simple -- just end the Image prematurely + if (m_FillMethod == FillMethod.Horizontal || m_FillMethod == FillMethod.Vertical) + { + if (fillMethod == FillMethod.Horizontal) + { + float fill = (tx1 - tx0) * m_FillAmount; + + if (m_FillOrigin == 1) + { + v.x = v.z - (v.z - v.x) * m_FillAmount; + tx0 = tx1 - fill; + } + else + { + v.z = v.x + (v.z - v.x) * m_FillAmount; + tx1 = tx0 + fill; + } + } + else if (fillMethod == FillMethod.Vertical) + { + float fill = (ty1 - ty0) * m_FillAmount; + + if (m_FillOrigin == 1) + { + v.y = v.w - (v.w - v.y) * m_FillAmount; + ty0 = ty1 - fill; + } + else + { + v.w = v.y + (v.w - v.y) * m_FillAmount; + ty1 = ty0 + fill; + } + } + } + + s_Xy[0] = new Vector2(v.x, v.y); + s_Xy[1] = new Vector2(v.x, v.w); + s_Xy[2] = new Vector2(v.z, v.w); + s_Xy[3] = new Vector2(v.z, v.y); + + s_Uv[0] = new Vector2(tx0, ty0); + s_Uv[1] = new Vector2(tx0, ty1); + s_Uv[2] = new Vector2(tx1, ty1); + s_Uv[3] = new Vector2(tx1, ty0); + + { + if (m_FillAmount < 1f && m_FillMethod != FillMethod.Horizontal && m_FillMethod != FillMethod.Vertical) + { + if (fillMethod == FillMethod.Radial90) + { + if (RadialCut(s_Xy, s_Uv, m_FillAmount, m_FillClockwise, m_FillOrigin)) + AddQuad(toFill, s_Xy, color, s_Uv); + } + else if (fillMethod == FillMethod.Radial180) + { + for (int side = 0; side < 2; ++side) + { + float fx0, fx1, fy0, fy1; + int even = m_FillOrigin > 1 ? 1 : 0; + + if (m_FillOrigin == 0 || m_FillOrigin == 2) + { + fy0 = 0f; + fy1 = 1f; + if (side == even) + { + fx0 = 0f; + fx1 = 0.5f; + } + else + { + fx0 = 0.5f; + fx1 = 1f; + } + } + else + { + fx0 = 0f; + fx1 = 1f; + if (side == even) + { + fy0 = 0.5f; + fy1 = 1f; + } + else + { + fy0 = 0f; + fy1 = 0.5f; + } + } + + s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0); + s_Xy[1].x = s_Xy[0].x; + s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1); + s_Xy[3].x = s_Xy[2].x; + + s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0); + s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1); + s_Xy[2].y = s_Xy[1].y; + s_Xy[3].y = s_Xy[0].y; + + s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0); + s_Uv[1].x = s_Uv[0].x; + s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1); + s_Uv[3].x = s_Uv[2].x; + + s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0); + s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1); + s_Uv[2].y = s_Uv[1].y; + s_Uv[3].y = s_Uv[0].y; + + float val = m_FillClockwise ? fillAmount * 2f - side : m_FillAmount * 2f - (1 - side); + + if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), m_FillClockwise, ((side + m_FillOrigin + 3) % 4))) + { + AddQuad(toFill, s_Xy, color, s_Uv); + } + } + } + else if (fillMethod == FillMethod.Radial360) + { + for (int corner = 0; corner < 4; ++corner) + { + float fx0, fx1, fy0, fy1; + + if (corner < 2) + { + fx0 = 0f; + fx1 = 0.5f; + } + else + { + fx0 = 0.5f; + fx1 = 1f; + } + + if (corner == 0 || corner == 3) + { + fy0 = 0f; + fy1 = 0.5f; + } + else + { + fy0 = 0.5f; + fy1 = 1f; + } + + s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0); + s_Xy[1].x = s_Xy[0].x; + s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1); + s_Xy[3].x = s_Xy[2].x; + + s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0); + s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1); + s_Xy[2].y = s_Xy[1].y; + s_Xy[3].y = s_Xy[0].y; + + s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0); + s_Uv[1].x = s_Uv[0].x; + s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1); + s_Uv[3].x = s_Uv[2].x; + + s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0); + s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1); + s_Uv[2].y = s_Uv[1].y; + s_Uv[3].y = s_Uv[0].y; + + float val = m_FillClockwise ? + m_FillAmount * 4f - ((corner + m_FillOrigin) % 4) : + m_FillAmount * 4f - (3 - ((corner + m_FillOrigin) % 4)); + + if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), m_FillClockwise, ((corner + 2) % 4))) + AddQuad(toFill, s_Xy, color, s_Uv); + } + } + } + else + { + AddQuad(toFill, s_Xy, color, s_Uv); + } + } + } + + /// + /// Adjust the specified quad, making it be radially filled instead. + /// + + static bool RadialCut(Vector3[] xy, Vector3[] uv, float fill, bool invert, int corner) + { + // Nothing to fill + if (fill < 0.001f) return false; + + // Even corners invert the fill direction + if ((corner & 1) == 1) invert = !invert; + + // Nothing to adjust + if (!invert && fill > 0.999f) return true; + + // Convert 0-1 value into 0 to 90 degrees angle in radians + float angle = Mathf.Clamp01(fill); + if (invert) angle = 1f - angle; + angle *= 90f * Mathf.Deg2Rad; + + // Calculate the effective X and Y factors + float cos = Mathf.Cos(angle); + float sin = Mathf.Sin(angle); + + RadialCut(xy, cos, sin, invert, corner); + RadialCut(uv, cos, sin, invert, corner); + return true; + } + + /// + /// Adjust the specified quad, making it be radially filled instead. + /// + + static void RadialCut(Vector3[] xy, float cos, float sin, bool invert, int corner) + { + int i0 = corner; + int i1 = ((corner + 1) % 4); + int i2 = ((corner + 2) % 4); + int i3 = ((corner + 3) % 4); + + if ((corner & 1) == 1) + { + if (sin > cos) + { + cos /= sin; + sin = 1f; + + if (invert) + { + xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos); + xy[i2].x = xy[i1].x; + } + } + else if (cos > sin) + { + sin /= cos; + cos = 1f; + + if (!invert) + { + xy[i2].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin); + xy[i3].y = xy[i2].y; + } + } + else + { + cos = 1f; + sin = 1f; + } + + if (!invert) xy[i3].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos); + else xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin); + } + else + { + if (cos > sin) + { + sin /= cos; + cos = 1f; + + if (!invert) + { + xy[i1].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin); + xy[i2].y = xy[i1].y; + } + } + else if (sin > cos) + { + cos /= sin; + sin = 1f; + + if (invert) + { + xy[i2].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos); + xy[i3].x = xy[i2].x; + } + } + else + { + cos = 1f; + sin = 1f; + } + + if (invert) xy[i3].y = Mathf.Lerp(xy[i0].y, xy[i2].y, sin); + else xy[i1].x = Mathf.Lerp(xy[i0].x, xy[i2].x, cos); + } + } + + public virtual void CalculateLayoutInputHorizontal() {} + public virtual void CalculateLayoutInputVertical() {} + + public virtual float minWidth { get { return 0; } } + + public virtual float preferredWidth + { + get + { + if (activeSprite == null) + return 0; + if (type == Type.Sliced || type == Type.Tiled) + return Sprites.DataUtility.GetMinSize(activeSprite).x / pixelsPerUnit; + return activeSprite.rect.size.x / pixelsPerUnit; + } + } + + public virtual float flexibleWidth { get { return -1; } } + + public virtual float minHeight { get { return 0; } } + + public virtual float preferredHeight + { + get + { + if (activeSprite == null) + return 0; + if (type == Type.Sliced || type == Type.Tiled) + return Sprites.DataUtility.GetMinSize(activeSprite).y / pixelsPerUnit; + return activeSprite.rect.size.y / pixelsPerUnit; + } + } + + public virtual float flexibleHeight { get { return -1; } } + + public virtual int layoutPriority { get { return 0; } } + + //会根据透明度做更细致的射线检测,透明的地方不算 + public virtual bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) + { + if (alphaHitTestMinimumThreshold <= 0) + return true; + + if (alphaHitTestMinimumThreshold > 1) + return false; + + if (activeSprite == null) + return true; + + Vector2 local; + if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local)) + return false; + + Rect rect = GetPixelAdjustedRect(); + + // Convert to have lower left corner as reference point. + local.x += rectTransform.pivot.x * rect.width; + local.y += rectTransform.pivot.y * rect.height; + + local = MapCoordinate(local, rect); + + // Normalize local coordinates. + Rect spriteRect = activeSprite.textureRect; + Vector2 normalized = new Vector2(local.x / spriteRect.width, local.y / spriteRect.height); + + // Convert to texture space. + float x = Mathf.Lerp(spriteRect.x, spriteRect.xMax, normalized.x) / activeSprite.texture.width; + float y = Mathf.Lerp(spriteRect.y, spriteRect.yMax, normalized.y) / activeSprite.texture.height; + + try + { + return activeSprite.texture.GetPixelBilinear(x, y).a >= alphaHitTestMinimumThreshold; + } + catch (UnityException e) + { + Debug.LogError("Using alphaHitTestMinimumThreshold greater than 0 on Image whose sprite texture cannot be read. " + e.Message + " Also make sure to disable sprite packing for this sprite.", this); + return true; + } + } + + private Vector2 MapCoordinate(Vector2 local, Rect rect) + { + Rect spriteRect = activeSprite.rect; + if (type == Type.Simple || type == Type.Filled) + return new Vector2(local.x * spriteRect.width / rect.width, local.y * spriteRect.height / rect.height); + + Vector4 border = activeSprite.border; + Vector4 adjustedBorder = GetAdjustedBorders(border / pixelsPerUnit, rect); + + for (int i = 0; i < 2; i++) + { + if (local[i] <= adjustedBorder[i]) + continue; + + if (rect.size[i] - local[i] <= adjustedBorder[i + 2]) + { + local[i] -= (rect.size[i] - spriteRect.size[i]); + continue; + } + + if (type == Type.Sliced) + { + float lerp = Mathf.InverseLerp(adjustedBorder[i], rect.size[i] - adjustedBorder[i + 2], local[i]); + local[i] = Mathf.Lerp(border[i], spriteRect.size[i] - border[i + 2], lerp); + continue; + } + else + { + local[i] -= adjustedBorder[i]; + local[i] = Mathf.Repeat(local[i], spriteRect.size[i] - border[i] - border[i + 2]); + local[i] += border[i]; + continue; + } + } + + return local; + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta new file mode 100644 index 0000000..91ab591 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/Image.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0cba8e295482e184f9f6a5a8f2b559c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs new file mode 100644 index 0000000..0d0f327 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs @@ -0,0 +1,235 @@ +using System; +using UnityEngine.Events; +using UnityEngine.Rendering; + +namespace UnityEngine.UI +{ + public abstract class MaskableGraphic : Graphic, IClippable, IMaskable, IMaterialModifier + { + [NonSerialized] + protected bool m_ShouldRecalculateStencil = true; + + [NonSerialized] + protected Material m_MaskMaterial; + + [NonSerialized] + private RectMask2D m_ParentMask; + + // m_Maskable is whether this graphic is allowed to be masked or not. It has the matching public property maskable. + // The default for m_Maskable is true, so graphics under a mask are masked out of the box. + // The maskable property can be turned off from script by the user if masking is not desired. + // m_IncludeForMasking is whether we actually consider this graphic for masking or not - this is an implementation detail. + // m_IncludeForMasking should only be true if m_Maskable is true AND a parent of the graphic has an IMask component. + // Things would still work correctly if m_IncludeForMasking was always true when m_Maskable is, but performance would suffer. + [NonSerialized] + private bool m_Maskable = true; + + [NonSerialized] + [Obsolete("Not used anymore.", true)] + protected bool m_IncludeForMasking = false; + + [Serializable] + public class CullStateChangedEvent : UnityEvent {} + + // Event delegates triggered on click. + [SerializeField] + private CullStateChangedEvent m_OnCullStateChanged = new CullStateChangedEvent(); + + public CullStateChangedEvent onCullStateChanged + { + get { return m_OnCullStateChanged; } + set { m_OnCullStateChanged = value; } + } + + public bool maskable + { + get { return m_Maskable; } + set + { + if (value == m_Maskable) + return; + m_Maskable = value; + m_ShouldRecalculateStencil = true; + SetMaterialDirty(); + } + } + + [NonSerialized] + [Obsolete("Not used anymore", true)] + protected bool m_ShouldRecalculate = true; + + [NonSerialized] + protected int m_StencilValue; + + public virtual Material GetModifiedMaterial(Material baseMaterial) + { + var toUse = baseMaterial; + + if (m_ShouldRecalculateStencil) + { + var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); + // Graphic在masks下的深度,如果不是0且没有mask组件意味着是普通的非mask用graphic(如果是0一定是mask用的graphic) + m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0; + m_ShouldRecalculateStencil = false; + } + + // if we have a enabled Mask component then it will + // generate the mask material. This is an optimisation + // it adds some coupling between components though :( + Mask maskComponent = GetComponent(); + if (m_StencilValue > 0 && (maskComponent == null || !maskComponent.IsActive())) + { + // Ref = (1 << stencilValue) - 1 + // Op = Keep + // Func = Equal + // ReadMask = (1 << stencilValue) - 1 + // WriteMask = 0 + var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0); + StencilMaterial.Remove(m_MaskMaterial); + m_MaskMaterial = maskMat; + toUse = m_MaskMaterial; + } + return toUse; + } + + public virtual void Cull(Rect clipRect, bool validRect) + { + var cull = !validRect || !clipRect.Overlaps(rootCanvasRect, true); + UpdateCull(cull); + } + + private void UpdateCull(bool cull) + { + var cullingChanged = canvasRenderer.cull != cull; + canvasRenderer.cull = cull; + + if (cullingChanged) + { + UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this); + m_OnCullStateChanged.Invoke(cull); + SetVerticesDirty(); // 这里需要更新一下canvasRenderer的网格数据 + } + } + + public virtual void SetClipRect(Rect clipRect, bool validRect) + { + if (validRect) + canvasRenderer.EnableRectClipping(clipRect); + else + canvasRenderer.DisableRectClipping(); + } + + protected override void OnEnable() + { + base.OnEnable(); + m_ShouldRecalculateStencil = true; + UpdateClipParent(); + SetMaterialDirty(); + + if (GetComponent() != null) + { + MaskUtilities.NotifyStencilStateChanged(this); + } + } + + protected override void OnDisable() + { + base.OnDisable(); + m_ShouldRecalculateStencil = true; + SetMaterialDirty(); + UpdateClipParent(); + StencilMaterial.Remove(m_MaskMaterial); + m_MaskMaterial = null; + + if (GetComponent() != null) + { + MaskUtilities.NotifyStencilStateChanged(this); + } + } + +#if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + m_ShouldRecalculateStencil = true; + UpdateClipParent(); + SetMaterialDirty(); + } + +#endif + + protected override void OnTransformParentChanged() + { + base.OnTransformParentChanged(); + + if (!isActiveAndEnabled) + return; + + m_ShouldRecalculateStencil = true; + UpdateClipParent(); + SetMaterialDirty(); + } + + [Obsolete("Not used anymore.", true)] + public virtual void ParentMaskStateChanged() {} + + protected override void OnCanvasHierarchyChanged() + { + base.OnCanvasHierarchyChanged(); + + if (!isActiveAndEnabled) + return; + + m_ShouldRecalculateStencil = true; + UpdateClipParent(); + SetMaterialDirty(); + } + + readonly Vector3[] m_Corners = new Vector3[4]; + private Rect rootCanvasRect + { + get + { + rectTransform.GetWorldCorners(m_Corners); + + if (canvas) + { + Canvas rootCanvas = canvas.rootCanvas; + for (int i = 0; i < 4; ++i) + m_Corners[i] = rootCanvas.transform.InverseTransformPoint(m_Corners[i]); + } + + return new Rect(m_Corners[0].x, m_Corners[0].y, m_Corners[2].x - m_Corners[0].x, m_Corners[2].y - m_Corners[0].y); + } + } + + private void UpdateClipParent() + { + var newParent = (maskable && IsActive()) ? MaskUtilities.GetRectMaskForClippable(this) : null; + + // if the new parent is different OR is now inactive + if (m_ParentMask != null && (newParent != m_ParentMask || !newParent.IsActive())) + { + m_ParentMask.RemoveClippable(this); + UpdateCull(false); + } + + // don't re-add it if the newparent is inactive + if (newParent != null && newParent.IsActive()) + newParent.AddClippable(this); + + m_ParentMask = newParent; + } + + public virtual void RecalculateClipping() + { + UpdateClipParent(); + } + + public virtual void RecalculateMasking() + { + m_ShouldRecalculateStencil = true; + SetMaterialDirty(); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs.meta new file mode 100644 index 0000000..07f0d51 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/MaskableGraphic.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1316d79994e789c448714be540d28f4f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs new file mode 100644 index 0000000..e6dab1b --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + /// + /// If you don't have or don't wish to create an atlas, you can simply use this script to draw a texture. + /// Keep in mind though that this will create an extra draw call with each RawImage present, so it's + /// best to use it only for backgrounds or temporary visible graphics. + /// + [AddComponentMenu("UI/Raw Image", 12)] + public class RawImage : MaskableGraphic + { + [FormerlySerializedAs("m_Tex")] + [SerializeField] Texture m_Texture; + [SerializeField] Rect m_UVRect = new Rect(0f, 0f, 1f, 1f); + + protected RawImage() + { + useLegacyMeshGeneration = false; + } + + /// + /// Returns the texture used to draw this Graphic. + /// + public override Texture mainTexture + { + get + { + if (m_Texture == null) + { + if (material != null && material.mainTexture != null) + { + return material.mainTexture; + } + return s_WhiteTexture; + } + return m_Texture; + } + } + + /// + /// Texture to be used. + /// + public Texture texture + { + get + { + return m_Texture; + } + set + { + if (m_Texture == value) + return; + + m_Texture = value; + SetVerticesDirty(); + SetMaterialDirty(); + } + } + + /// + /// UV rectangle used by the texture. + /// + public Rect uvRect + { + get + { + return m_UVRect; + } + set + { + if (m_UVRect == value) + return; + m_UVRect = value; + SetVerticesDirty(); + } + } + + /// + /// Adjust the scale of the Graphic to make it pixel-perfect. + /// + + public override void SetNativeSize() + { + Texture tex = mainTexture; + if (tex != null) + { + int w = Mathf.RoundToInt(tex.width * uvRect.width); + int h = Mathf.RoundToInt(tex.height * uvRect.height); + rectTransform.anchorMax = rectTransform.anchorMin; + rectTransform.sizeDelta = new Vector2(w, h); + } + } + + protected override void OnPopulateMesh(VertexHelper vh) + { + Texture tex = mainTexture; + vh.Clear(); + if (tex != null) + { + var r = GetPixelAdjustedRect(); + var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height); + var scaleX = tex.width * tex.texelSize.x; + var scaleY = tex.height * tex.texelSize.y; + { + var color32 = color; + vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(m_UVRect.xMin * scaleX, m_UVRect.yMin * scaleY)); + vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(m_UVRect.xMin * scaleX, m_UVRect.yMax * scaleY)); + vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(m_UVRect.xMax * scaleX, m_UVRect.yMax * scaleY)); + vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(m_UVRect.xMax * scaleX, m_UVRect.yMin * scaleY)); + + vh.AddTriangle(0, 1, 2); + vh.AddTriangle(2, 3, 0); + } + } + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta new file mode 100644 index 0000000..2a70e35 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/RawImage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 570773b73e8b0334fb410b7457eb8b6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs new file mode 100644 index 0000000..c95e146 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs @@ -0,0 +1,33 @@ +using System; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + [Serializable] + public struct SpriteState : IEquatable + { + [FormerlySerializedAs("highlightedSprite")] + [FormerlySerializedAs("m_SelectedSprite")] + [SerializeField] + private Sprite m_HighlightedSprite; + + [FormerlySerializedAs("pressedSprite")] + [SerializeField] + private Sprite m_PressedSprite; + + [FormerlySerializedAs("disabledSprite")] + [SerializeField] + private Sprite m_DisabledSprite; + + public Sprite highlightedSprite { get { return m_HighlightedSprite; } set { m_HighlightedSprite = value; } } + public Sprite pressedSprite { get { return m_PressedSprite; } set { m_PressedSprite = value; } } + public Sprite disabledSprite { get { return m_DisabledSprite; } set { m_DisabledSprite = value; } } + + public bool Equals(SpriteState other) + { + return highlightedSprite == other.highlightedSprite && + pressedSprite == other.pressedSprite && + disabledSprite == other.disabledSprite; + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta new file mode 100644 index 0000000..b389ded --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Graphics/SpriteState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc6d0c85730bc354697c6b7d971eda44 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout.meta new file mode 100644 index 0000000..28d0b9d --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0bcd17013ce6d5a4ab037dcc71a87811 +folderAsset: yes +timeCreated: 1602119280 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs new file mode 100644 index 0000000..96ee135 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs @@ -0,0 +1,145 @@ +using UnityEngine.EventSystems; + +namespace UnityEngine.UI +{ + [AddComponentMenu("Layout/Aspect Ratio Fitter", 142)] + [ExecuteInEditMode] + [RequireComponent(typeof(RectTransform))] + [DisallowMultipleComponent] + public class AspectRatioFitter : UIBehaviour, ILayoutSelfController + { + public enum AspectMode { None, WidthControlsHeight, HeightControlsWidth, FitInParent, EnvelopeParent } + + [SerializeField] private AspectMode m_AspectMode = AspectMode.None; + public AspectMode aspectMode { get { return m_AspectMode; } set { if (SetPropertyUtility.SetStruct(ref m_AspectMode, value)) SetDirty(); } } + + [SerializeField] private float m_AspectRatio = 1; + public float aspectRatio { get { return m_AspectRatio; } set { if (SetPropertyUtility.SetStruct(ref m_AspectRatio, value)) SetDirty(); } } + + [System.NonSerialized] + private RectTransform m_Rect; + + private RectTransform rectTransform + { + get + { + if (m_Rect == null) + m_Rect = GetComponent(); + return m_Rect; + } + } + + private DrivenRectTransformTracker m_Tracker; + + protected AspectRatioFitter() {} + + protected override void OnEnable() + { + base.OnEnable(); + SetDirty(); + } + + protected override void OnDisable() + { + m_Tracker.Clear(); + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + base.OnDisable(); + } + + protected override void OnRectTransformDimensionsChange() + { + UpdateRect(); + } + + private void UpdateRect() + { + if (!IsActive()) + return; + + m_Tracker.Clear(); + + switch (m_AspectMode) + { +#if UNITY_EDITOR + case AspectMode.None: + { + if (!Application.isPlaying) + m_AspectRatio = Mathf.Clamp(rectTransform.rect.width / rectTransform.rect.height, 0.001f, 1000f); + + break; + } +#endif + case AspectMode.HeightControlsWidth: + { + m_Tracker.Add(this, rectTransform, DrivenTransformProperties.SizeDeltaX); + rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, rectTransform.rect.height * m_AspectRatio); + break; + } + case AspectMode.WidthControlsHeight: + { + m_Tracker.Add(this, rectTransform, DrivenTransformProperties.SizeDeltaY); + rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, rectTransform.rect.width / m_AspectRatio); + break; + } + case AspectMode.FitInParent: + case AspectMode.EnvelopeParent: + { + m_Tracker.Add(this, rectTransform, + DrivenTransformProperties.Anchors | + DrivenTransformProperties.AnchoredPosition | + DrivenTransformProperties.SizeDeltaX | + DrivenTransformProperties.SizeDeltaY); + + rectTransform.anchorMin = Vector2.zero; + rectTransform.anchorMax = Vector2.one; + rectTransform.anchoredPosition = Vector2.zero; + + Vector2 sizeDelta = Vector2.zero; + Vector2 parentSize = GetParentSize(); + if ((parentSize.y * aspectRatio < parentSize.x) ^ (m_AspectMode == AspectMode.FitInParent)) + { + sizeDelta.y = GetSizeDeltaToProduceSize(parentSize.x / aspectRatio, 1); + } + else + { + sizeDelta.x = GetSizeDeltaToProduceSize(parentSize.y * aspectRatio, 0); + } + rectTransform.sizeDelta = sizeDelta; + + break; + } + } + } + + private float GetSizeDeltaToProduceSize(float size, int axis) + { + return size - GetParentSize()[axis] * (rectTransform.anchorMax[axis] - rectTransform.anchorMin[axis]); + } + + private Vector2 GetParentSize() + { + RectTransform parent = rectTransform.parent as RectTransform; + if (!parent) + return Vector2.zero; + return parent.rect.size; + } + + public virtual void SetLayoutHorizontal() {} + + public virtual void SetLayoutVertical() {} + + protected void SetDirty() + { + UpdateRect(); + } + + #if UNITY_EDITOR + protected override void OnValidate() + { + m_AspectRatio = Mathf.Clamp(m_AspectRatio, 0.001f, 1000f); + SetDirty(); + } + + #endif + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs.meta new file mode 100644 index 0000000..e89adeb --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/AspectRatioFitter.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 49604c30279a7aa44b531ad6ffea458c +timeCreated: 1602119378 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs new file mode 100644 index 0000000..6504ac2 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs @@ -0,0 +1,241 @@ +using UnityEngine.EventSystems; + +namespace UnityEngine.UI +{ + [RequireComponent(typeof(Canvas))] + [ExecuteInEditMode] + [AddComponentMenu("Layout/Canvas Scaler", 101)] + public class CanvasScaler : UIBehaviour + { + public enum ScaleMode { ConstantPixelSize, ScaleWithScreenSize, ConstantPhysicalSize } + + [Tooltip("Determines how UI elements in the Canvas are scaled.")] + [SerializeField] private ScaleMode m_UiScaleMode = ScaleMode.ConstantPixelSize; + public ScaleMode uiScaleMode { get { return m_UiScaleMode; } set { m_UiScaleMode = value; } } + + [Tooltip("If a sprite has this 'Pixels Per Unit' setting, then one pixel in the sprite will cover one unit in the UI.")] + [SerializeField] protected float m_ReferencePixelsPerUnit = 100; + public float referencePixelsPerUnit { get { return m_ReferencePixelsPerUnit; } set { m_ReferencePixelsPerUnit = value; } } + + + // Constant Pixel Size settings + + [Tooltip("Scales all UI elements in the Canvas by this factor.")] + [SerializeField] protected float m_ScaleFactor = 1; + public float scaleFactor { get { return m_ScaleFactor; } set { m_ScaleFactor = Mathf.Max(0.01f, value); } } + + + // Scale With Screen Size settings + + public enum ScreenMatchMode { MatchWidthOrHeight = 0, Expand = 1, Shrink = 2 } + + [Tooltip("The resolution the UI layout is designed for. If the screen resolution is larger, the UI will be scaled up, and if it's smaller, the UI will be scaled down. This is done in accordance with the Screen Match Mode.")] + [SerializeField] protected Vector2 m_ReferenceResolution = new Vector2(800, 600); + public Vector2 referenceResolution + { + get + { + return m_ReferenceResolution; + } + set + { + m_ReferenceResolution = value; + + const float k_MinimumResolution = 0.00001f; + + if (m_ReferenceResolution.x > -k_MinimumResolution && m_ReferenceResolution.x < k_MinimumResolution) m_ReferenceResolution.x = k_MinimumResolution * Mathf.Sign(m_ReferenceResolution.x); + if (m_ReferenceResolution.y > -k_MinimumResolution && m_ReferenceResolution.y < k_MinimumResolution) m_ReferenceResolution.y = k_MinimumResolution * Mathf.Sign(m_ReferenceResolution.y); + } + } + + [Tooltip("A mode used to scale the canvas area if the aspect ratio of the current resolution doesn't fit the reference resolution.")] + [SerializeField] protected ScreenMatchMode m_ScreenMatchMode = ScreenMatchMode.MatchWidthOrHeight; + public ScreenMatchMode screenMatchMode { get { return m_ScreenMatchMode; } set { m_ScreenMatchMode = value; } } + + [Tooltip("Determines if the scaling is using the width or height as reference, or a mix in between.")] + [Range(0, 1)] + [SerializeField] protected float m_MatchWidthOrHeight = 0; + public float matchWidthOrHeight { get { return m_MatchWidthOrHeight; } set { m_MatchWidthOrHeight = value; } } + + // The log base doesn't have any influence on the results whatsoever, as long as the same base is used everywhere. + private const float kLogBase = 2; + + + // Constant Physical Size settings + + public enum Unit { Centimeters, Millimeters, Inches, Points, Picas } + + [Tooltip("The physical unit to specify positions and sizes in.")] + [SerializeField] protected Unit m_PhysicalUnit = Unit.Points; + public Unit physicalUnit { get { return m_PhysicalUnit; } set { m_PhysicalUnit = value; } } + + [Tooltip("The DPI to assume if the screen DPI is not known.")] + [SerializeField] protected float m_FallbackScreenDPI = 96; + public float fallbackScreenDPI { get { return m_FallbackScreenDPI; } set { m_FallbackScreenDPI = value; } } + + [Tooltip("The pixels per inch to use for sprites that have a 'Pixels Per Unit' setting that matches the 'Reference Pixels Per Unit' setting.")] + [SerializeField] protected float m_DefaultSpriteDPI = 96; + public float defaultSpriteDPI { get { return m_DefaultSpriteDPI; } set { m_DefaultSpriteDPI = Mathf.Max(1, value); } } + + + // World Canvas settings + + [Tooltip("The amount of pixels per unit to use for dynamically created bitmaps in the UI, such as Text.")] + [SerializeField] protected float m_DynamicPixelsPerUnit = 1; + public float dynamicPixelsPerUnit { get { return m_DynamicPixelsPerUnit; } set { m_DynamicPixelsPerUnit = value; } } + + + // General variables + + private Canvas m_Canvas; + [System.NonSerialized] + private float m_PrevScaleFactor = 1; + [System.NonSerialized] + private float m_PrevReferencePixelsPerUnit = 100; + + + protected CanvasScaler() {} + + protected override void OnEnable() + { + base.OnEnable(); + m_Canvas = GetComponent(); + Handle(); + } + + protected override void OnDisable() + { + SetScaleFactor(1); + SetReferencePixelsPerUnit(100); + base.OnDisable(); + } + + protected virtual void Update() + { + Handle(); + } + + protected virtual void Handle() + { + if (m_Canvas == null || !m_Canvas.isRootCanvas) + return; + + if (m_Canvas.renderMode == RenderMode.WorldSpace) + { + HandleWorldCanvas(); + return; + } + + switch (m_UiScaleMode) + { + case ScaleMode.ConstantPixelSize: HandleConstantPixelSize(); break; + case ScaleMode.ScaleWithScreenSize: HandleScaleWithScreenSize(); break; + case ScaleMode.ConstantPhysicalSize: HandleConstantPhysicalSize(); break; + } + } + + protected virtual void HandleWorldCanvas() + { + SetScaleFactor(m_DynamicPixelsPerUnit); + SetReferencePixelsPerUnit(m_ReferencePixelsPerUnit); + } + + protected virtual void HandleConstantPixelSize() + { + SetScaleFactor(m_ScaleFactor); + SetReferencePixelsPerUnit(m_ReferencePixelsPerUnit); + } + + protected virtual void HandleScaleWithScreenSize() + { + Vector2 screenSize = new Vector2(Screen.width, Screen.height); + + // Multiple display support only when not the main display. For display 0 the reported + // resolution is always the desktops resolution since its part of the display API, + // so we use the standard none multiple display method. (case 741751) + int displayIndex = m_Canvas.targetDisplay; + if (displayIndex > 0 && displayIndex < Display.displays.Length) + { + Display disp = Display.displays[displayIndex]; + screenSize = new Vector2(disp.renderingWidth, disp.renderingHeight); + } + + float scaleFactor = 0; + switch (m_ScreenMatchMode) + { + case ScreenMatchMode.MatchWidthOrHeight: + { + // We take the log of the relative width and height before taking the average. + // Then we transform it back in the original space. + // the reason to transform in and out of logarithmic space is to have better behavior. + // If one axis has twice resolution and the other has half, it should even out if widthOrHeight value is at 0.5. + // In normal space the average would be (0.5 + 2) / 2 = 1.25 + // In logarithmic space the average is (-1 + 1) / 2 = 0 + float logWidth = Mathf.Log(screenSize.x / m_ReferenceResolution.x, kLogBase); + float logHeight = Mathf.Log(screenSize.y / m_ReferenceResolution.y, kLogBase); + float logWeightedAverage = Mathf.Lerp(logWidth, logHeight, m_MatchWidthOrHeight); + scaleFactor = Mathf.Pow(kLogBase, logWeightedAverage); + break; + } + case ScreenMatchMode.Expand: + { + scaleFactor = Mathf.Min(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y); + break; + } + case ScreenMatchMode.Shrink: + { + scaleFactor = Mathf.Max(screenSize.x / m_ReferenceResolution.x, screenSize.y / m_ReferenceResolution.y); + break; + } + } + + SetScaleFactor(scaleFactor); + SetReferencePixelsPerUnit(m_ReferencePixelsPerUnit); + } + + protected virtual void HandleConstantPhysicalSize() + { + float currentDpi = Screen.dpi; + float dpi = (currentDpi == 0 ? m_FallbackScreenDPI : currentDpi); + float targetDPI = 1; + switch (m_PhysicalUnit) + { + case Unit.Centimeters: targetDPI = 2.54f; break; + case Unit.Millimeters: targetDPI = 25.4f; break; + case Unit.Inches: targetDPI = 1; break; + case Unit.Points: targetDPI = 72; break; + case Unit.Picas: targetDPI = 6; break; + } + + SetScaleFactor(dpi / targetDPI); + SetReferencePixelsPerUnit(m_ReferencePixelsPerUnit * targetDPI / m_DefaultSpriteDPI); + } + + protected void SetScaleFactor(float scaleFactor) + { + if (scaleFactor == m_PrevScaleFactor) + return; + + m_Canvas.scaleFactor = scaleFactor; + m_PrevScaleFactor = scaleFactor; + } + + protected void SetReferencePixelsPerUnit(float referencePixelsPerUnit) + { + if (referencePixelsPerUnit == m_PrevReferencePixelsPerUnit) + return; + + m_Canvas.referencePixelsPerUnit = referencePixelsPerUnit; + m_PrevReferencePixelsPerUnit = referencePixelsPerUnit; + } + +#if UNITY_EDITOR + protected override void OnValidate() + { + m_ScaleFactor = Mathf.Max(0.01f, m_ScaleFactor); + m_DefaultSpriteDPI = Mathf.Max(1, m_DefaultSpriteDPI); + } + +#endif + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs.meta new file mode 100644 index 0000000..4d67413 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: debcf26b89013e446a6de5574715c5af +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs new file mode 100644 index 0000000..a31d14c --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs @@ -0,0 +1,103 @@ +using UnityEngine.EventSystems; + +namespace UnityEngine.UI +{ + [AddComponentMenu("Layout/Content Size Fitter", 141)] + [ExecuteInEditMode] + [RequireComponent(typeof(RectTransform))] + public class ContentSizeFitter : UIBehaviour, ILayoutSelfController + { + public enum FitMode + { + Unconstrained, + MinSize, + PreferredSize + } + + [SerializeField] protected FitMode m_HorizontalFit = FitMode.Unconstrained; + public FitMode horizontalFit { get { return m_HorizontalFit; } set { if (SetPropertyUtility.SetStruct(ref m_HorizontalFit, value)) SetDirty(); } } + + [SerializeField] protected FitMode m_VerticalFit = FitMode.Unconstrained; + public FitMode verticalFit { get { return m_VerticalFit; } set { if (SetPropertyUtility.SetStruct(ref m_VerticalFit, value)) SetDirty(); } } + + [System.NonSerialized] private RectTransform m_Rect; + private RectTransform rectTransform + { + get + { + if (m_Rect == null) + m_Rect = GetComponent(); + return m_Rect; + } + } + + private DrivenRectTransformTracker m_Tracker; + + protected ContentSizeFitter() + {} + + protected override void OnEnable() + { + base.OnEnable(); + SetDirty(); + } + + protected override void OnDisable() + { + m_Tracker.Clear(); + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + base.OnDisable(); + } + + protected override void OnRectTransformDimensionsChange() + { + SetDirty(); + } + + private void HandleSelfFittingAlongAxis(int axis) + { + FitMode fitting = (axis == 0 ? horizontalFit : verticalFit); + if (fitting == FitMode.Unconstrained) + { + // Keep a reference to the tracked transform, but don't control its properties: + m_Tracker.Add(this, rectTransform, DrivenTransformProperties.None); + return; + } + + m_Tracker.Add(this, rectTransform, (axis == 0 ? DrivenTransformProperties.SizeDeltaX : DrivenTransformProperties.SizeDeltaY)); + + // Set size to min or preferred size + if (fitting == FitMode.MinSize) + rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetMinSize(m_Rect, axis)); + else + rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetPreferredSize(m_Rect, axis)); + } + + public virtual void SetLayoutHorizontal() + { + m_Tracker.Clear(); + HandleSelfFittingAlongAxis(0); + } + + public virtual void SetLayoutVertical() + { + HandleSelfFittingAlongAxis(1); + } + + protected void SetDirty() + { + if (!IsActive()) + return; + + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + } + + #if UNITY_EDITOR + protected override void OnValidate() + { + SetDirty(); + } + + #endif + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs.meta new file mode 100644 index 0000000..9f31a6d --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ContentSizeFitter.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 742ec49dc902c1f4db49d19ada047c0e +timeCreated: 1602119379 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs new file mode 100644 index 0000000..170e410 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs @@ -0,0 +1,207 @@ +using UnityEngine; +using System.Collections.Generic; + +namespace UnityEngine.UI +{ + [AddComponentMenu("Layout/Grid Layout Group", 152)] + public class GridLayoutGroup : LayoutGroup + { + public enum Corner { UpperLeft = 0, UpperRight = 1, LowerLeft = 2, LowerRight = 3 } + public enum Axis { Horizontal = 0, Vertical = 1 } + public enum Constraint { Flexible = 0, FixedColumnCount = 1, FixedRowCount = 2 } + + [SerializeField] protected Corner m_StartCorner = Corner.UpperLeft; + public Corner startCorner { get { return m_StartCorner; } set { SetProperty(ref m_StartCorner, value); } } + + [SerializeField] protected Axis m_StartAxis = Axis.Horizontal; + public Axis startAxis { get { return m_StartAxis; } set { SetProperty(ref m_StartAxis, value); } } + + [SerializeField] protected Vector2 m_CellSize = new Vector2(100, 100); + public Vector2 cellSize { get { return m_CellSize; } set { SetProperty(ref m_CellSize, value); } } + + [SerializeField] protected Vector2 m_Spacing = Vector2.zero; + public Vector2 spacing { get { return m_Spacing; } set { SetProperty(ref m_Spacing, value); } } + + [SerializeField] protected Constraint m_Constraint = Constraint.Flexible; + public Constraint constraint { get { return m_Constraint; } set { SetProperty(ref m_Constraint, value); } } + + [SerializeField] protected int m_ConstraintCount = 2; + public int constraintCount { get { return m_ConstraintCount; } set { SetProperty(ref m_ConstraintCount, Mathf.Max(1, value)); } } + + protected GridLayoutGroup() + {} + + #if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + constraintCount = constraintCount; + } + + #endif + + public override void CalculateLayoutInputHorizontal() + { + base.CalculateLayoutInputHorizontal(); + + int minColumns = 0; + int preferredColumns = 0; + if (m_Constraint == Constraint.FixedColumnCount) + { + minColumns = preferredColumns = m_ConstraintCount; + } + else if (m_Constraint == Constraint.FixedRowCount) + { + minColumns = preferredColumns = Mathf.CeilToInt(rectChildren.Count / (float)m_ConstraintCount - 0.001f); + } + else + { + minColumns = 1; + preferredColumns = Mathf.CeilToInt(Mathf.Sqrt(rectChildren.Count)); + } + + SetLayoutInputForAxis( + padding.horizontal + (cellSize.x + spacing.x) * minColumns - spacing.x, + padding.horizontal + (cellSize.x + spacing.x) * preferredColumns - spacing.x, + -1, 0); + } + + public override void CalculateLayoutInputVertical() + { + int minRows = 0; + if (m_Constraint == Constraint.FixedColumnCount) + { + minRows = Mathf.CeilToInt(rectChildren.Count / (float)m_ConstraintCount - 0.001f); + } + else if (m_Constraint == Constraint.FixedRowCount) + { + minRows = m_ConstraintCount; + } + else + { + float width = rectTransform.rect.size.x; + int cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))); + minRows = Mathf.CeilToInt(rectChildren.Count / (float)cellCountX); + } + + float minSpace = padding.vertical + (cellSize.y + spacing.y) * minRows - spacing.y; + SetLayoutInputForAxis(minSpace, minSpace, -1, 1); + } + + public override void SetLayoutHorizontal() + { + SetCellsAlongAxis(0); + } + + public override void SetLayoutVertical() + { + SetCellsAlongAxis(1); + } + + private void SetCellsAlongAxis(int axis) + { + // Normally a Layout Controller should only set horizontal values when invoked for the horizontal axis + // and only vertical values when invoked for the vertical axis. + // However, in this case we set both the horizontal and vertical position when invoked for the vertical axis. + // Since we only set the horizontal position and not the size, it shouldn't affect children's layout, + // and thus shouldn't break the rule that all horizontal layout must be calculated before all vertical layout. + + if (axis == 0) + { + // Only set the sizes when invoked for horizontal axis, not the positions. + for (int i = 0; i < rectChildren.Count; i++) + { + RectTransform rect = rectChildren[i]; + + m_Tracker.Add(this, rect, + DrivenTransformProperties.Anchors | + DrivenTransformProperties.AnchoredPosition | + DrivenTransformProperties.SizeDelta); + + rect.anchorMin = Vector2.up; + rect.anchorMax = Vector2.up; + rect.sizeDelta = cellSize; + } + return; + } + + float width = rectTransform.rect.size.x; + float height = rectTransform.rect.size.y; + + int cellCountX = 1; + int cellCountY = 1; + if (m_Constraint == Constraint.FixedColumnCount) + { + cellCountX = m_ConstraintCount; + cellCountY = Mathf.CeilToInt(rectChildren.Count / (float)cellCountX - 0.001f); + } + else if (m_Constraint == Constraint.FixedRowCount) + { + cellCountY = m_ConstraintCount; + cellCountX = Mathf.CeilToInt(rectChildren.Count / (float)cellCountY - 0.001f); + } + else + { + if (cellSize.x + spacing.x <= 0) + cellCountX = int.MaxValue; + else + cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))); + + if (cellSize.y + spacing.y <= 0) + cellCountY = int.MaxValue; + else + cellCountY = Mathf.Max(1, Mathf.FloorToInt((height - padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y))); + } + + int cornerX = (int)startCorner % 2; + int cornerY = (int)startCorner / 2; + + int cellsPerMainAxis, actualCellCountX, actualCellCountY; + if (startAxis == Axis.Horizontal) + { + cellsPerMainAxis = cellCountX; + actualCellCountX = Mathf.Clamp(cellCountX, 1, rectChildren.Count); + actualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(rectChildren.Count / (float)cellsPerMainAxis)); + } + else + { + cellsPerMainAxis = cellCountY; + actualCellCountY = Mathf.Clamp(cellCountY, 1, rectChildren.Count); + actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(rectChildren.Count / (float)cellsPerMainAxis)); + } + + Vector2 requiredSpace = new Vector2( + actualCellCountX * cellSize.x + (actualCellCountX - 1) * spacing.x, + actualCellCountY * cellSize.y + (actualCellCountY - 1) * spacing.y + ); + Vector2 startOffset = new Vector2( + GetStartOffset(0, requiredSpace.x), + GetStartOffset(1, requiredSpace.y) + ); + + for (int i = 0; i < rectChildren.Count; i++) + { + int positionX; + int positionY; + if (startAxis == Axis.Horizontal) + { + positionX = i % cellsPerMainAxis; + positionY = i / cellsPerMainAxis; + } + else + { + positionX = i / cellsPerMainAxis; + positionY = i % cellsPerMainAxis; + } + + if (cornerX == 1) + positionX = actualCellCountX - 1 - positionX; + if (cornerY == 1) + positionY = actualCellCountY - 1 - positionY; + + SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (cellSize[0] + spacing[0]) * positionX, cellSize[0]); + SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]); + } + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs.meta new file mode 100644 index 0000000..0ca5454 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/GridLayoutGroup.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 295d2cd868a0c204f850fde4917c4551 +timeCreated: 1602119378 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs new file mode 100644 index 0000000..efe8d8e --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs @@ -0,0 +1,30 @@ +namespace UnityEngine.UI +{ + [AddComponentMenu("Layout/Horizontal Layout Group", 150)] + public class HorizontalLayoutGroup : HorizontalOrVerticalLayoutGroup + { + protected HorizontalLayoutGroup() + {} + + public override void CalculateLayoutInputHorizontal() + { + base.CalculateLayoutInputHorizontal(); + CalcAlongAxis(0, false); + } + + public override void CalculateLayoutInputVertical() + { + CalcAlongAxis(1, false); + } + + public override void SetLayoutHorizontal() + { + SetChildrenAlongAxis(0, false); + } + + public override void SetLayoutVertical() + { + SetChildrenAlongAxis(1, false); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs.meta new file mode 100644 index 0000000..0b116be --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalLayoutGroup.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 2e0c30f216d393d4b93475ba573aea85 +timeCreated: 1602119378 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs new file mode 100644 index 0000000..3e1c923 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs @@ -0,0 +1,179 @@ +namespace UnityEngine.UI +{ + // 布局算法的核心都在这个基类里面 + public abstract class HorizontalOrVerticalLayoutGroup : LayoutGroup + { + [SerializeField] protected float m_Spacing = 0; + public float spacing { get { return m_Spacing; } set { SetProperty(ref m_Spacing, value); } } + + [SerializeField] protected bool m_ChildForceExpandWidth = true; + public bool childForceExpandWidth { get { return m_ChildForceExpandWidth; } set { SetProperty(ref m_ChildForceExpandWidth, value); } } + + [SerializeField] protected bool m_ChildForceExpandHeight = true; + public bool childForceExpandHeight { get { return m_ChildForceExpandHeight; } set { SetProperty(ref m_ChildForceExpandHeight, value); } } + + [SerializeField] protected bool m_ChildControlWidth = true; + public bool childControlWidth { get { return m_ChildControlWidth; } set { SetProperty(ref m_ChildControlWidth, value); } } + + [SerializeField] protected bool m_ChildControlHeight = true; + public bool childControlHeight { get { return m_ChildControlHeight; } set { SetProperty(ref m_ChildControlHeight, value); } } + + // 根据子节点计算得到自身的min, preferred, flexible + protected void CalcAlongAxis(int axis, bool isVertical) + { + float combinedPadding = (axis == 0 ? padding.horizontal : padding.vertical); // padding是left+right, top+bottom + bool controlSize = (axis == 0 ? m_ChildControlWidth : m_ChildControlHeight); + bool childForceExpandSize = (axis == 0 ? childForceExpandWidth : childForceExpandHeight); + + float totalMin = combinedPadding; // 所有子节点的min之和 + float totalPreferred = combinedPadding; // 所有子节点的preferred之和 + float totalFlexible = 0; // 是一个无单位数值,等于所有子节点的flexible值相加 + + bool alongOtherAxis = (isVertical ^ (axis == 1)); + for (int i = 0; i < rectChildren.Count; i++) + { + RectTransform child = rectChildren[i]; + float min, preferred, flexible; // 子节点的三个属性值 + GetChildSizes(child, axis, controlSize, childForceExpandSize, out min, out preferred, out flexible); + + if (alongOtherAxis) + { + totalMin = Mathf.Max(min + combinedPadding, totalMin); + totalPreferred = Mathf.Max(preferred + combinedPadding, totalPreferred); + totalFlexible = Mathf.Max(flexible, totalFlexible); + } + else + { + totalMin += min + spacing; + totalPreferred += preferred + spacing; + + // Increment flexible size with element's flexible size. + totalFlexible += flexible; + } + } + + // 减去最后一个子节点多加的spacing + if (!alongOtherAxis && rectChildren.Count > 0) + { + totalMin -= spacing; + totalPreferred -= spacing; + } + + totalPreferred = Mathf.Max(totalMin, totalPreferred); + // 保存到m_TotalMinSize, m_TotalPreferredSize, m_TotalFlexibleSize + SetLayoutInputForAxis(totalMin, totalPreferred, totalFlexible, axis); + } + + protected void SetChildrenAlongAxis(int axis, bool isVertical) + { + float size = rectTransform.rect.size[axis]; // RectTransform大小 + bool controlSize = (axis == 0 ? m_ChildControlWidth : m_ChildControlHeight); + bool childForceExpandSize = (axis == 0 ? childForceExpandWidth : childForceExpandHeight); + float alignmentOnAxis = GetAlignmentOnAxis(axis); + + bool alongOtherAxis = (isVertical ^ (axis == 1)); + if (alongOtherAxis) + { + float innerSize = size - (axis == 0 ? padding.horizontal : padding.vertical); // 容纳子节点的空间 + for (int i = 0; i < rectChildren.Count; i++) + { + RectTransform child = rectChildren[i]; + float min, preferred, flexible; + GetChildSizes(child, axis, controlSize, childForceExpandSize, out min, out preferred, out flexible); + + float requiredSpace = Mathf.Clamp(innerSize, min, flexible > 0 ? size : preferred); + float startOffset = GetStartOffset(axis, requiredSpace); + if (controlSize) + { + SetChildAlongAxis(child, axis, startOffset, requiredSpace); + } + else + { + float offsetInCell = (requiredSpace - child.sizeDelta[axis]) * alignmentOnAxis; + SetChildAlongAxis(child, axis, startOffset + offsetInCell); + } + } + } + else + { + float pos = (axis == 0 ? padding.left : padding.top); + if (GetTotalFlexibleSize(axis) == 0 && GetTotalPreferredSize(axis) < size) + pos = GetStartOffset(axis, GetTotalPreferredSize(axis) - (axis == 0 ? padding.horizontal : padding.vertical)); + + float minMaxLerp = 0; // 塞进min之后的剩余空间/preferred-min的空间,是子节点从min向preferred扩大的依据 + if (GetTotalMinSize(axis) != GetTotalPreferredSize(axis)) + minMaxLerp = Mathf.Clamp01((size - GetTotalMinSize(axis)) / (GetTotalPreferredSize(axis) - GetTotalMinSize(axis))); + + float itemFlexibleMultiplier = 0; // 塞进preferred之后,进一步塞满剩余空间的依据,即flexible + if (size > GetTotalPreferredSize(axis)) + { + if (GetTotalFlexibleSize(axis) > 0) + itemFlexibleMultiplier = (size - GetTotalPreferredSize(axis)) / GetTotalFlexibleSize(axis); + } + + for (int i = 0; i < rectChildren.Count; i++) + { + RectTransform child = rectChildren[i]; + float min, preferred, flexible; + GetChildSizes(child, axis, controlSize, childForceExpandSize, out min, out preferred, out flexible); + + float childSize = Mathf.Lerp(min, preferred, minMaxLerp); + childSize += flexible * itemFlexibleMultiplier; + if (controlSize) + { + // 设置子节点的transform + SetChildAlongAxis(child, axis, pos, childSize); + } + else + { + float offsetInCell = (childSize - child.sizeDelta[axis]) * alignmentOnAxis; + SetChildAlongAxis(child, axis, pos + offsetInCell); + } + pos += childSize + spacing; + } + } + } + + // 返回节点的min, prefered, flexible大小 + // axis 0是x轴,1是y轴 + // controlSize 是否勾选ChildControlSize + // childForceExpand 是否勾选ChildForceExpand + private void GetChildSizes(RectTransform child, int axis, bool controlSize, bool childForceExpand, + out float min, out float preferred, out float flexible) + { + if (!controlSize) // 如果没勾ChildControlSize,那么会忽略 + { + min = child.sizeDelta[axis];//sizeDelta这里等价于size,因为动态布局系统里面anchor都是一起的 + preferred = min; + flexible = 0; + } + else + { + min = LayoutUtility.GetMinSize(child, axis); + preferred = LayoutUtility.GetPreferredSize(child, axis); + flexible = LayoutUtility.GetFlexibleSize(child, axis); + } + + if (childForceExpand) + flexible = Mathf.Max(flexible, 1); + } + +#if UNITY_EDITOR + protected override void Reset() + { + base.Reset(); + + // For new added components we want these to be set to false, + // so that the user's sizes won't be overwritten before they + // have a chance to turn these settings off. + // However, for existing components that were added before this + // feature was introduced, we want it to be on be default for + // backwardds compatibility. + // Hence their default value is on, but we set to off in reset. + m_ChildControlWidth = false; + m_ChildControlHeight = false; + } + +#endif + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs.meta new file mode 100644 index 0000000..4eaf7af --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/HorizontalOrVerticalLayoutGroup.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e33d83c2ebb040d459eaafaae66cc5e9 +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs new file mode 100644 index 0000000..d0e1510 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs @@ -0,0 +1,50 @@ +using UnityEngine; +using System.Collections; + +namespace UnityEngine.UI +{ + public interface ILayoutElement + { +#region LayoutGroup的派生类才会实现,其他ILayoutElement比如Image,Text不会实现 + // After this method is invoked, layout horizontal input properties should return up-to-date values. + // Children will already have up-to-date layout horizontal inputs when this methods is called. + void CalculateLayoutInputHorizontal(); + // After this method is invoked, layout vertical input properties should return up-to-date values. + // Children will already have up-to-date layout vertical inputs when this methods is called. + void CalculateLayoutInputVertical(); +#endregion + + // Layout horizontal inputs + float minWidth { get; } + float preferredWidth { get; } + float flexibleWidth { get; } + // Layout vertical inputs + float minHeight { get; } + float preferredHeight { get; } + float flexibleHeight { get; } + + int layoutPriority { get; } + } + + public interface ILayoutController + { + void SetLayoutHorizontal(); + void SetLayoutVertical(); + } + + // An ILayoutGroup component should drive the RectTransforms of its children. + public interface ILayoutGroup : ILayoutController + { + } + + // An ILayoutSelfController component should drive its own RectTransform. + public interface ILayoutSelfController : ILayoutController + { + } + + // An ILayoutIgnorer component is ignored by the auto-layout system. + public interface ILayoutIgnorer + { + bool ignoreLayout { get; } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs.meta new file mode 100644 index 0000000..f115b8f --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/ILayoutElement.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9437925aea643a84f8ab4da3d03c183d +timeCreated: 1602119379 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs new file mode 100644 index 0000000..cdee245 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs @@ -0,0 +1,78 @@ +using UnityEngine.EventSystems; + +namespace UnityEngine.UI +{ + [AddComponentMenu("Layout/Layout Element", 140)] + [RequireComponent(typeof(RectTransform))] + [ExecuteInEditMode] + public class LayoutElement : UIBehaviour, ILayoutElement, ILayoutIgnorer + { + [SerializeField] private bool m_IgnoreLayout = false; + [SerializeField] private float m_MinWidth = -1; + [SerializeField] private float m_MinHeight = -1; + [SerializeField] private float m_PreferredWidth = -1; + [SerializeField] private float m_PreferredHeight = -1; + [SerializeField] private float m_FlexibleWidth = -1; + [SerializeField] private float m_FlexibleHeight = -1; + [SerializeField] private int m_LayoutPriority = 1; + + + public virtual bool ignoreLayout { get { return m_IgnoreLayout; } set { if (SetPropertyUtility.SetStruct(ref m_IgnoreLayout, value)) SetDirty(); } } + + public virtual void CalculateLayoutInputHorizontal() {} + public virtual void CalculateLayoutInputVertical() {} + public virtual float minWidth { get { return m_MinWidth; } set { if (SetPropertyUtility.SetStruct(ref m_MinWidth, value)) SetDirty(); } } + public virtual float minHeight { get { return m_MinHeight; } set { if (SetPropertyUtility.SetStruct(ref m_MinHeight, value)) SetDirty(); } } + public virtual float preferredWidth { get { return m_PreferredWidth; } set { if (SetPropertyUtility.SetStruct(ref m_PreferredWidth, value)) SetDirty(); } } + public virtual float preferredHeight { get { return m_PreferredHeight; } set { if (SetPropertyUtility.SetStruct(ref m_PreferredHeight, value)) SetDirty(); } } + public virtual float flexibleWidth { get { return m_FlexibleWidth; } set { if (SetPropertyUtility.SetStruct(ref m_FlexibleWidth, value)) SetDirty(); } } + public virtual float flexibleHeight { get { return m_FlexibleHeight; } set { if (SetPropertyUtility.SetStruct(ref m_FlexibleHeight, value)) SetDirty(); } } + public virtual int layoutPriority { get { return m_LayoutPriority; } set { if (SetPropertyUtility.SetStruct(ref m_LayoutPriority, value)) SetDirty(); } } + + + protected LayoutElement() + {} + + protected override void OnEnable() + { + base.OnEnable(); + SetDirty(); + } + + protected override void OnTransformParentChanged() + { + SetDirty(); + } + + protected override void OnDisable() + { + SetDirty(); + base.OnDisable(); + } + + protected override void OnDidApplyAnimationProperties() + { + SetDirty(); + } + + protected override void OnBeforeTransformParentChanged() + { + SetDirty(); + } + + protected void SetDirty() + { + if (!IsActive()) + return; + LayoutRebuilder.MarkLayoutForRebuild(transform as RectTransform); + } + + #if UNITY_EDITOR + protected override void OnValidate() + { + SetDirty(); + } + + #endif + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs.meta new file mode 100644 index 0000000..40cc6f9 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutElement.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 1ae73daeb8941804886a5ec8aa41dc2a +timeCreated: 1602119377 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs new file mode 100644 index 0000000..6a17e00 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs @@ -0,0 +1,237 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine.EventSystems; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + [DisallowMultipleComponent] + [ExecuteInEditMode] + [RequireComponent(typeof(RectTransform))] + public abstract class LayoutGroup : UIBehaviour, ILayoutElement, ILayoutGroup + { + [SerializeField] protected RectOffset m_Padding = new RectOffset(); + public RectOffset padding { get { return m_Padding; } set { SetProperty(ref m_Padding, value); } } + + [FormerlySerializedAs("m_Alignment")] + [SerializeField] protected TextAnchor m_ChildAlignment = TextAnchor.UpperLeft; + public TextAnchor childAlignment { get { return m_ChildAlignment; } set { SetProperty(ref m_ChildAlignment, value); } } + + [System.NonSerialized] private RectTransform m_Rect; + protected RectTransform rectTransform + { + get + { + if (m_Rect == null) + m_Rect = GetComponent(); + return m_Rect; + } + } + + protected DrivenRectTransformTracker m_Tracker; + private Vector2 m_TotalMinSize = Vector2.zero; + private Vector2 m_TotalPreferredSize = Vector2.zero; + private Vector2 m_TotalFlexibleSize = Vector2.zero; + + [System.NonSerialized] private List m_RectChildren = new List(); + protected List rectChildren { get { return m_RectChildren; } } + + + // ILayoutElement Interface + // 收集子节点中参与布局的节点 + public virtual void CalculateLayoutInputHorizontal() + { + m_RectChildren.Clear(); + var toIgnoreList = ListPool.Get(); + for (int i = 0; i < rectTransform.childCount; i++) + { + var rect = rectTransform.GetChild(i) as RectTransform; + if (rect == null || !rect.gameObject.activeInHierarchy) + continue; + + rect.GetComponents(typeof(ILayoutIgnorer), toIgnoreList); + + if (toIgnoreList.Count == 0) + { + m_RectChildren.Add(rect); + continue; + } + + for (int j = 0; j < toIgnoreList.Count; j++) + { + var ignorer = (ILayoutIgnorer)toIgnoreList[j]; + if (!ignorer.ignoreLayout) + { + m_RectChildren.Add(rect); + break; + } + } + } + ListPool.Release(toIgnoreList); + m_Tracker.Clear(); + } + + // 这个方法不收集是因为在CalculateLayoutInputHorizontal收集了,在LayoutRebuilder的Rebuild()方法中有注释 + public abstract void CalculateLayoutInputVertical(); + public virtual float minWidth { get { return GetTotalMinSize(0); } } + public virtual float preferredWidth { get { return GetTotalPreferredSize(0); } } + public virtual float flexibleWidth { get { return GetTotalFlexibleSize(0); } } + public virtual float minHeight { get { return GetTotalMinSize(1); } } + public virtual float preferredHeight { get { return GetTotalPreferredSize(1); } } + public virtual float flexibleHeight { get { return GetTotalFlexibleSize(1); } } + public virtual int layoutPriority { get { return 0; } } + + // ILayoutController Interface + + public abstract void SetLayoutHorizontal(); + public abstract void SetLayoutVertical(); + + // Implementation + + protected LayoutGroup() + { + if (m_Padding == null) + m_Padding = new RectOffset(); + } + + protected override void OnEnable() + { + base.OnEnable(); + SetDirty(); + } + + protected override void OnDisable() + { + m_Tracker.Clear(); + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + base.OnDisable(); + } + + protected override void OnDidApplyAnimationProperties() + { + SetDirty(); + } + + protected float GetTotalMinSize(int axis) + { + return m_TotalMinSize[axis]; + } + + protected float GetTotalPreferredSize(int axis) + { + return m_TotalPreferredSize[axis]; + } + + protected float GetTotalFlexibleSize(int axis) + { + return m_TotalFlexibleSize[axis]; + } + + protected float GetStartOffset(int axis, float requiredSpaceWithoutPadding) + { + float requiredSpace = requiredSpaceWithoutPadding + (axis == 0 ? padding.horizontal : padding.vertical); // 算上padding后的大小 + float availableSpace = rectTransform.rect.size[axis]; // RectTransform大小 + float surplusSpace = availableSpace - requiredSpace; // 剩余空间 + float alignmentOnAxis = GetAlignmentOnAxis(axis); // 0\0.5\1 + return (axis == 0 ? padding.left : padding.top) + surplusSpace * alignmentOnAxis; + } + + protected float GetAlignmentOnAxis(int axis) + { + if (axis == 0) + return ((int)childAlignment % 3) * 0.5f; // 0, 0.5, 1 + else + return ((int)childAlignment / 3) * 0.5f; // 0, 0.5, 1 + } + + protected void SetLayoutInputForAxis(float totalMin, float totalPreferred, float totalFlexible, int axis) + { + m_TotalMinSize[axis] = totalMin; + m_TotalPreferredSize[axis] = totalPreferred; + m_TotalFlexibleSize[axis] = totalFlexible; + } + + protected void SetChildAlongAxis(RectTransform rect, int axis, float pos) + { + if (rect == null) + return; + + m_Tracker.Add(this, rect, + DrivenTransformProperties.Anchors | + (axis == 0 ? DrivenTransformProperties.AnchoredPositionX : DrivenTransformProperties.AnchoredPositionY)); + + rect.SetInsetAndSizeFromParentEdge(axis == 0 ? RectTransform.Edge.Left : RectTransform.Edge.Top, pos, rect.sizeDelta[axis]); + } + + protected void SetChildAlongAxis(RectTransform rect, int axis, float pos, float size) + { + if (rect == null) + return; + + m_Tracker.Add(this, rect, + DrivenTransformProperties.Anchors | + (axis == 0 ? + (DrivenTransformProperties.AnchoredPositionX | DrivenTransformProperties.SizeDeltaX) : + (DrivenTransformProperties.AnchoredPositionY | DrivenTransformProperties.SizeDeltaY) + )); + + rect.SetInsetAndSizeFromParentEdge(axis == 0 ? RectTransform.Edge.Left : RectTransform.Edge.Top, pos, size); + } + + private bool isRootLayoutGroup + { + get + { + Transform parent = transform.parent; + if (parent == null) + return true; + return transform.parent.GetComponent(typeof(ILayoutGroup)) == null; + } + } + + protected override void OnRectTransformDimensionsChange() + { + base.OnRectTransformDimensionsChange(); + if (isRootLayoutGroup) + SetDirty(); + } + + protected virtual void OnTransformChildrenChanged() + { + SetDirty(); + } + + protected void SetProperty(ref T currentValue, T newValue) + { + if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue))) + return; + currentValue = newValue; + SetDirty(); + } + + protected void SetDirty() + { + if (!IsActive()) + return; + + if (!CanvasUpdateRegistry.IsRebuildingLayout()) + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + else + StartCoroutine(DelayedSetDirty(rectTransform)); + } + + IEnumerator DelayedSetDirty(RectTransform rectTransform) + { + yield return null; + LayoutRebuilder.MarkLayoutForRebuild(rectTransform); + } + + #if UNITY_EDITOR + protected override void OnValidate() + { + SetDirty(); + } + + #endif + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs.meta new file mode 100644 index 0000000..2c5525c --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutGroup.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 5094cec73437de8479168e16d201c2c6 +timeCreated: 1602119378 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs new file mode 100644 index 0000000..5fba1cc --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs @@ -0,0 +1,233 @@ +using System.Collections.Generic; +using UnityEngine.Events; + +namespace UnityEngine.UI +{ + public class LayoutRebuilder : ICanvasElement + { + // m_ToRebuild是一个ILayoutGroup + private RectTransform m_ToRebuild; + //There are a few of reasons we need to cache the Hash from the transform: + // - This is a ValueType (struct) and .Net calculates Hash from the Value Type fields. + // - The key of a Dictionary should have a constant Hash value. + // - It's possible for the Transform to get nulled from the Native side. + // We use this struct with the IndexedSet container, which uses a dictionary as part of it's implementation + // So this struct gets used as a key to a dictionary, so we need to guarantee a constant Hash value. + private int m_CachedHashFromTransform; + + // 一个rebuilder结构的池子 + static ObjectPool s_Rebuilders = new ObjectPool(null, x => x.Clear()); + + private void Initialize(RectTransform controller) + { + m_ToRebuild = controller; + m_CachedHashFromTransform = controller.GetHashCode(); + } + + private void Clear() + { + m_ToRebuild = null; + m_CachedHashFromTransform = 0; + } + + static LayoutRebuilder() + { + RectTransform.reapplyDrivenProperties += ReapplyDrivenProperties; + } + + static void ReapplyDrivenProperties(RectTransform driven) + { + MarkLayoutForRebuild(driven); + } + + public Transform transform { get { return m_ToRebuild; }} + + public bool IsDestroyed() + { + return m_ToRebuild == null; + } + + static void StripDisabledBehavioursFromList(List components) + { + components.RemoveAll(e => e is Behaviour && !((Behaviour)e).isActiveAndEnabled); + } + + // 立即重新布局一次,而不用等到帧末尾CanvasUpdateReigstry.PerformUpdate的时候 + public static void ForceRebuildLayoutImmediate(RectTransform layoutRoot) + { + var rebuilder = s_Rebuilders.Get(); + rebuilder.Initialize(layoutRoot); + rebuilder.Rebuild(CanvasUpdate.Layout); + s_Rebuilders.Release(rebuilder); + } + + public void Rebuild(CanvasUpdate executing) + { + switch (executing) + { + case CanvasUpdate.Layout: + // It's unfortunate that we'll perform the same GetComponents querys for the tree 2 times, + // but each tree have to be fully iterated before going to the next action, + // so reusing the results would entail storing results in a Dictionary or similar, + // which is probably a bigger overhead than performing GetComponents multiple times. + PerformLayoutCalculation(m_ToRebuild, e => (e as ILayoutElement).CalculateLayoutInputHorizontal()); + PerformLayoutControl(m_ToRebuild, e => (e as ILayoutController).SetLayoutHorizontal()); + PerformLayoutCalculation(m_ToRebuild, e => (e as ILayoutElement).CalculateLayoutInputVertical()); + PerformLayoutControl(m_ToRebuild, e => (e as ILayoutController).SetLayoutVertical()); + break; + } + } + + // 从上到下遍历,执行action + private void PerformLayoutControl(RectTransform rect, UnityAction action) + { + if (rect == null) + return; + + var components = ListPool.Get(); + rect.GetComponents(typeof(ILayoutController), components); + StripDisabledBehavioursFromList(components); + + // If there are no controllers on this rect we can skip this entire sub-tree + // We don't need to consider controllers on children deeper in the sub-tree either, + // since they will be their own roots. + if (components.Count > 0) + { + // + // Layout control needs to executed top down with parents being done before their children, + // because the children rely on the sizes of the parents. + + // 做两次遍历,先执行ILayoutSelfController比如ContentSizeFitter,再执行ILayoutGroup + + // First call layout controllers that may change their own RectTransform + for (int i = 0; i < components.Count; i++) + if (components[i] is ILayoutSelfController) + action(components[i]); + + // Then call the remaining, such as layout groups that change their children, taking their own RectTransform size into account. + for (int i = 0; i < components.Count; i++) + if (!(components[i] is ILayoutSelfController)) + action(components[i]); + + for (int i = 0; i < rect.childCount; i++) + PerformLayoutControl(rect.GetChild(i) as RectTransform, action); + } + + ListPool.Release(components); + } + + private void PerformLayoutCalculation(RectTransform rect, UnityAction action) + { + if (rect == null) + return; + + var components = ListPool.Get(); + rect.GetComponents(typeof(ILayoutElement), components); + StripDisabledBehavioursFromList(components); + + // If there are no controllers on this rect we can skip this entire sub-tree + // We don't need to consider controllers on children deeper in the sub-tree either, + // since they will be their own roots. + if (components.Count > 0 || rect.GetComponent(typeof(ILayoutGroup))) + { + + // 先从子节点开始,最后到父节点,这样父节点可以得到子节点的信息 + // Layout calculations needs to executed bottom up with children being done before their parents, + // because the parent calculated sizes rely on the sizes of the children. + + for (int i = 0; i < rect.childCount; i++) + PerformLayoutCalculation(rect.GetChild(i) as RectTransform, action); + + for (int i = 0; i < components.Count; i++) + action(components[i]); + } + + ListPool.Release(components); + } + + // 找到rect祖先节点中的layoutGroup并加入队列 + public static void MarkLayoutForRebuild(RectTransform rect) + { + if (rect == null) + return; + + var comps = ListPool.Get(); + RectTransform layoutRoot = rect; // 祖先节点中的layoutGroup + while (true) + { + var parent = layoutRoot.parent as RectTransform; + if (!ValidLayoutGroup(parent, comps)) + break; + layoutRoot = parent; + } + + // We know the layout root is valid if it's not the same as the rect, + // since we checked that above. But if they're the same we still need to check. + if (layoutRoot == rect && !ValidController(layoutRoot, comps)) + { + ListPool.Release(comps); + return; + } + + MarkLayoutRootForRebuild(layoutRoot); + ListPool.Release(comps); + } + + private static bool ValidLayoutGroup(RectTransform parent, List comps) + { + if (parent == null) + return false; + + parent.GetComponents(typeof(ILayoutGroup), comps); + StripDisabledBehavioursFromList(comps); + var validCount = comps.Count > 0; + return validCount; + } + + private static bool ValidController(RectTransform layoutRoot, List comps) + { + if (layoutRoot == null) + return false; + layoutRoot.GetComponents(typeof(ILayoutController), comps); + StripDisabledBehavioursFromList(comps); + var valid = comps.Count > 0; + return valid; + } + + private static void MarkLayoutRootForRebuild(RectTransform controller) + { + if (controller == null) + return; + + var rebuilder = s_Rebuilders.Get(); + rebuilder.Initialize(controller); + // 注册到CanvasUpdateRegistry里 + if (!CanvasUpdateRegistry.TryRegisterCanvasElementForLayoutRebuild(rebuilder)) + s_Rebuilders.Release(rebuilder); + } + + public void LayoutComplete() + { + // 放回池子里 + s_Rebuilders.Release(this); + } + + public void GraphicUpdateComplete() + {} + + public override int GetHashCode() + { + return m_CachedHashFromTransform; + } + + public override bool Equals(object obj) + { + return obj.GetHashCode() == GetHashCode(); + } + + public override string ToString() + { + return "(Layout Rebuilder for) " + m_ToRebuild; + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs.meta new file mode 100644 index 0000000..ad21a40 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutRebuilder.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 297af0346d9a6b24e88b4dbdfae053e0 +timeCreated: 1602119378 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs new file mode 100644 index 0000000..c58abd5 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs @@ -0,0 +1,112 @@ +using UnityEngine; +using System.Collections.Generic; +using UnityEngine.Events; + +namespace UnityEngine.UI +{ + public static class LayoutUtility + { + public static float GetMinSize(RectTransform rect, int axis) + { + if (axis == 0) + return GetMinWidth(rect); + return GetMinHeight(rect); + } + + public static float GetPreferredSize(RectTransform rect, int axis) + { + if (axis == 0) + return GetPreferredWidth(rect); + return GetPreferredHeight(rect); + } + + public static float GetFlexibleSize(RectTransform rect, int axis) + { + if (axis == 0) + return GetFlexibleWidth(rect); + return GetFlexibleHeight(rect); + } + + public static float GetMinWidth(RectTransform rect) + { + return GetLayoutProperty(rect, e => e.minWidth, 0); + } + + public static float GetPreferredWidth(RectTransform rect) + { + return Mathf.Max(GetLayoutProperty(rect, e => e.minWidth, 0), GetLayoutProperty(rect, e => e.preferredWidth, 0)); + } + + public static float GetFlexibleWidth(RectTransform rect) + { + return GetLayoutProperty(rect, e => e.flexibleWidth, 0); + } + + public static float GetMinHeight(RectTransform rect) + { + return GetLayoutProperty(rect, e => e.minHeight, 0); + } + + public static float GetPreferredHeight(RectTransform rect) + { + return Mathf.Max(GetLayoutProperty(rect, e => e.minHeight, 0), GetLayoutProperty(rect, e => e.preferredHeight, 0)); + } + + public static float GetFlexibleHeight(RectTransform rect) + { + return GetLayoutProperty(rect, e => e.flexibleHeight, 0); + } + + public static float GetLayoutProperty(RectTransform rect, System.Func property, float defaultValue) + { + ILayoutElement dummy; + return GetLayoutProperty(rect, property, defaultValue, out dummy); + } + + public static float GetLayoutProperty(RectTransform rect, System.Func property, float defaultValue, out ILayoutElement source) + { + source = null; + if (rect == null) + return 0; + float min = defaultValue; + int maxPriority = System.Int32.MinValue; + var components = ListPool.Get(); + rect.GetComponents(typeof(ILayoutElement), components); + + for (int i = 0; i < components.Count; i++) + { + var layoutComp = components[i] as ILayoutElement; // + if (layoutComp is Behaviour && !((Behaviour)layoutComp).isActiveAndEnabled) + continue; + + int priority = layoutComp.layoutPriority; + // If this layout components has lower priority than a previously used, ignore it. + if (priority < maxPriority) + continue; + float prop = property(layoutComp); + // If this layout property is set to a negative value, it means it should be ignored. + if (prop < 0) + continue; + + // If this layout component has higher priority than all previous ones, + // overwrite with this one's value. + if (priority > maxPriority) + { + min = prop; + maxPriority = priority; + source = layoutComp; + } + // If the layout component has the same priority as a previously used, + // use the largest of the values with the same priority. + else if (prop > min) + { + min = prop; + source = layoutComp; + } + } + + ListPool.Release(components); + return min; + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs.meta new file mode 100644 index 0000000..e0d1878 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/LayoutUtility.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d180430718b19fe4786c73f6e7c798fa +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs new file mode 100644 index 0000000..e24b842 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs @@ -0,0 +1,30 @@ +namespace UnityEngine.UI +{ + [AddComponentMenu("Layout/Vertical Layout Group", 151)] + public class VerticalLayoutGroup : HorizontalOrVerticalLayoutGroup + { + protected VerticalLayoutGroup() + {} + + public override void CalculateLayoutInputHorizontal() + { + base.CalculateLayoutInputHorizontal(); + CalcAlongAxis(0, true); + } + + public override void CalculateLayoutInputVertical() + { + CalcAlongAxis(1, true); + } + + public override void SetLayoutHorizontal() + { + SetChildrenAlongAxis(0, true); + } + + public override void SetLayoutVertical() + { + SetChildrenAlongAxis(1, true); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs.meta new file mode 100644 index 0000000..9b945bf --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Layout/VerticalLayoutGroup.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f050f1af13388a145b34f3d0b59c8955 +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask.meta new file mode 100644 index 0000000..ad6af48 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3bc3203fe03d7b049ae99a951f541714 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs new file mode 100644 index 0000000..ffe7aed --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs @@ -0,0 +1,11 @@ +using System; + +namespace UnityEngine.UI +{ + [Obsolete("Not supported anymore.", true)] + public interface IMask + { + bool Enabled(); + RectTransform rectTransform { get; } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta new file mode 100644 index 0000000..2eab58a --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d54c702726ac4fa4daf18719b41de69f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs new file mode 100644 index 0000000..8f8a28c --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs @@ -0,0 +1,9 @@ +using System; + +namespace UnityEngine.UI +{ + public interface IMaskable + { + void RecalculateMasking(); + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta new file mode 100644 index 0000000..298aac8 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/IMaskable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5775a30dcbc6e484c8795bb7e18ada44 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs new file mode 100644 index 0000000..c67ec42 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs @@ -0,0 +1,203 @@ +using System; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.Rendering; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + [AddComponentMenu("UI/Mask", 13)] + [ExecuteInEditMode] + [RequireComponent(typeof(RectTransform))] + [DisallowMultipleComponent] + public class Mask : UIBehaviour, ICanvasRaycastFilter, IMaterialModifier + { + [NonSerialized] + private RectTransform m_RectTransform; + public RectTransform rectTransform + { + get { return m_RectTransform ?? (m_RectTransform = GetComponent()); } + } + + [SerializeField] + [FormerlySerializedAs("m_ShowGraphic")] + private bool m_ShowMaskGraphic = true; + public bool showMaskGraphic + { + get { return m_ShowMaskGraphic; } + set + { + if (m_ShowMaskGraphic == value) + return; + + m_ShowMaskGraphic = value; + if (graphic != null) + graphic.SetMaterialDirty(); + } + } + + [NonSerialized] private Graphic m_Graphic; + public Graphic graphic + { + get { return m_Graphic ?? (m_Graphic = GetComponent()); } + } + + [NonSerialized] private Material m_MaskMaterial; + + [NonSerialized] private Material m_UnmaskMaterial; + + protected Mask() + {} + + public virtual bool MaskEnabled() { return IsActive() && graphic != null; } + + [Obsolete("Not used anymore.")] + public virtual void OnSiblingGraphicEnabledDisabled() {} + + protected override void OnEnable() + { + base.OnEnable(); + if (graphic != null) + { + graphic.canvasRenderer.hasPopInstruction = true; + graphic.SetMaterialDirty(); + } + + MaskUtilities.NotifyStencilStateChanged(this); + } + + protected override void OnDisable() + { + // we call base OnDisable first here + // as we need to have the IsActive return the + // correct value when we notify the children + // that the mask state has changed. + base.OnDisable(); + if (graphic != null) + { + graphic.SetMaterialDirty(); + graphic.canvasRenderer.hasPopInstruction = false; + graphic.canvasRenderer.popMaterialCount = 0; + } + + StencilMaterial.Remove(m_MaskMaterial); + m_MaskMaterial = null; + StencilMaterial.Remove(m_UnmaskMaterial); + m_UnmaskMaterial = null; + + MaskUtilities.NotifyStencilStateChanged(this); + } + +#if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + + if (!IsActive()) + return; + + if (graphic != null) + graphic.SetMaterialDirty(); + + MaskUtilities.NotifyStencilStateChanged(this); + } + +#endif + + public virtual bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) + { + if (!isActiveAndEnabled) + return true; + + return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera); + } + + /// Stencil calculation time! + public virtual Material GetModifiedMaterial(Material baseMaterial) + { + if (!MaskEnabled()) + return baseMaterial; + + var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); + var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas); + if (stencilDepth >= 8) // 不支持8层及以上的mask, 0-7支持,这是因为stencilRef和stencilMask只有一个字节 + { + Debug.LogError("Attempting to use a stencil mask with depth > 8", gameObject); + return baseMaterial; + } + + int desiredStencilBit = 1 << stencilDepth; + + // if we are at the first level... + // we want to destroy what is there + if (desiredStencilBit == 1) // 最上层的mask + { + // Ref = 1 + // Op = Replace + // Func = Always + // ReadMask = 255 + // WriteMask = 255 + var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0); + StencilMaterial.Remove(m_MaskMaterial); + m_MaskMaterial = maskMaterial; + + // Ref = 1 + // Op = Zero + // Func = Always + // ReadMask = 255 + // WriteMask = 255 + var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0); + StencilMaterial.Remove(m_UnmaskMaterial); + m_UnmaskMaterial = unmaskMaterial; + graphic.canvasRenderer.popMaterialCount = 1; + graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); + + return m_MaskMaterial; + } + + // Ref = desiredStencilBit | (desiredStencilBit - 1) + // Op = Replace + // Func = Equal + // ReadMask = desiredStencilBit - 1 + // WriteMask = desiredStencilBit | (desiredStencilBit - 1) + + //otherwise we need to be a bit smarter and set some read / write masks + var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); + StencilMaterial.Remove(m_MaskMaterial); + m_MaskMaterial = maskMaterial2; + + // Ref = desiredStencilBit - 1 + // Op = Replace + // Func = Equal + // ReadMask = desiredStencilBit - 1 + // WriteMask = desiredStencilBit | (desiredStencilBit - 1) + graphic.canvasRenderer.hasPopInstruction = true; + var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1)); + StencilMaterial.Remove(m_UnmaskMaterial); + m_UnmaskMaterial = unmaskMaterial2; + graphic.canvasRenderer.popMaterialCount = 1; + graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0); + + return m_MaskMaterial; + } + + + #region UGUI_DEBUG + + Vector3[] cornors = new Vector3[4]; + + void OnDrawGizmos() + { + Rect rect = rectTransform.rect; + Gizmos.color = Color.yellow; + rectTransform.GetWorldCorners(cornors); + for (int i = 0; i < cornors.Length; ++i) + { + Gizmos.DrawLine(cornors[i], cornors[(i + 1) % cornors.Length]); + } + } + + #endregion + + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta new file mode 100644 index 0000000..50caa3d --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/Mask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bfc675de41855c44aaedb7af695ba899 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs new file mode 100644 index 0000000..6abce5a --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs @@ -0,0 +1,187 @@ +using System.Collections.Generic; +using UnityEngine.EventSystems; + +namespace UnityEngine.UI +{ + public class MaskUtilities + { + public static void Notify2DMaskStateChanged(Component mask) + { + var components = ListPool.Get(); + mask.GetComponentsInChildren(components); + for (var i = 0; i < components.Count; i++) + { + if (components[i] == null || components[i].gameObject == mask.gameObject) + continue; + + var toNotify = components[i] as IClippable; + if (toNotify != null) + toNotify.RecalculateClipping(); + } + ListPool.Release(components); + } + + public static void NotifyStencilStateChanged(Component mask) + { + var components = ListPool.Get(); + mask.GetComponentsInChildren(components); + for (var i = 0; i < components.Count; i++) + { + if (components[i] == null || components[i].gameObject == mask.gameObject) + continue; + + var toNotify = components[i] as IMaskable; + if (toNotify != null) + toNotify.RecalculateMasking(); + } + ListPool.Release(components); + } + + //从下往上找到第一个OverrideSorting的canvas或者root(即null) + public static Transform FindRootSortOverrideCanvas(Transform start) + { + var canvasList = ListPool.Get(); + start.GetComponentsInParent(false, canvasList); + Canvas canvas = null; + + for (int i = 0; i < canvasList.Count; ++i) + { + canvas = canvasList[i]; + + // We found the canvas we want to use break + if (canvas.overrideSorting) + break; + } + ListPool.Release(canvasList); + + return canvas != null ? canvas.transform : null; + } + + // 返回Mask在canvas下(canvas下所有的masks下)的深度 + public static int GetStencilDepth(Transform transform, Transform stopAfter) + { + var depth = 0; + if (transform == stopAfter) + return depth; + + var t = transform.parent; + var components = ListPool.Get(); + while (t != null) + { + t.GetComponents(components); + for (var i = 0; i < components.Count; ++i) + { + if (components[i] != null && components[i].MaskEnabled() && components[i].graphic.IsActive()) + { + ++depth; + break; + } + } + + if (t == stopAfter) + break; + + t = t.parent; + } + ListPool.Release(components); + return depth; + } + + // father是child的祖先节点或者father == child + public static bool IsDescendantOrSelf(Transform father, Transform child) + { + if (father == null || child == null) + return false; + + if (father == child) + return true; + + while (child.parent != null) + { + if (child.parent == father) + return true; + + child = child.parent; + } + + return false; + } + + public static RectMask2D GetRectMaskForClippable(IClippable clippable) + { + List rectMaskComponents = ListPool.Get(); + List canvasComponents = ListPool.Get(); + RectMask2D componentToReturn = null; + + clippable.rectTransform.GetComponentsInParent(false, rectMaskComponents); + + if (rectMaskComponents.Count > 0) + { + for (int rmi = 0; rmi < rectMaskComponents.Count; rmi++) + { + componentToReturn = rectMaskComponents[rmi]; + if (componentToReturn.gameObject == clippable.gameObject) + { + componentToReturn = null; + continue; + } + if (!componentToReturn.isActiveAndEnabled) + { + componentToReturn = null; + continue; + } + clippable.rectTransform.GetComponentsInParent(false, canvasComponents); + for (int i = canvasComponents.Count - 1; i >= 0; i--) + { + if (!IsDescendantOrSelf(canvasComponents[i].transform, componentToReturn.transform) && canvasComponents[i].overrideSorting) + { + componentToReturn = null; + break; + } + } + return componentToReturn; + } + } + + ListPool.Release(rectMaskComponents); + ListPool.Release(canvasComponents); + + return componentToReturn; + } + + public static void GetRectMasksForClip(RectMask2D clipper, List masks) + { + masks.Clear(); + + List canvasComponents = ListPool.Get(); + List rectMaskComponents = ListPool.Get(); + clipper.transform.GetComponentsInParent(false, rectMaskComponents); + + if (rectMaskComponents.Count > 0) + { + clipper.transform.GetComponentsInParent(false, canvasComponents); + for (int i = rectMaskComponents.Count - 1; i >= 0; i--) + { + if (!rectMaskComponents[i].IsActive()) + continue; + bool shouldAdd = true; + for (int j = canvasComponents.Count - 1; j >= 0; j--) + { + // 如果rectMask2D是canvas的祖先节点且这个canvas勾选了OverrideSorting,那么这个rectMask2D就会失效 + if (!IsDescendantOrSelf(canvasComponents[j].transform, rectMaskComponents[i].transform) + && canvasComponents[j].overrideSorting) + { + shouldAdd = false; + break; + } + } + if (shouldAdd) + masks.Add(rectMaskComponents[i]); + } + } + + ListPool.Release(rectMaskComponents); + ListPool.Release(canvasComponents); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta new file mode 100644 index 0000000..5e7829c --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/MaskUtilities.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 469f0aa53de5d4c4fb69e83419090a01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs new file mode 100644 index 0000000..d973b34 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using UnityEngine.EventSystems; + +namespace UnityEngine.UI +{ + [AddComponentMenu("UI/Rect Mask 2D", 13)] + [ExecuteInEditMode] + [DisallowMultipleComponent] + [RequireComponent(typeof(RectTransform))] + public class RectMask2D : UIBehaviour, IClipper, ICanvasRaycastFilter + { + [NonSerialized] + private readonly RectangularVertexClipper m_VertexClipper = new RectangularVertexClipper(); + + [NonSerialized] + private RectTransform m_RectTransform; + + // 可裁剪的Graphics + [NonSerialized] + private HashSet m_ClipTargets = new HashSet(); + + [NonSerialized] + private bool m_ShouldRecalculateClipRects; + + // 父节点的所有RectMask2D,用来算交集 + [NonSerialized] + private List m_Clippers = new List(); + + [NonSerialized] + private Rect m_LastClipRectCanvasSpace; + [NonSerialized] + private bool m_LastValidClipRect; + [NonSerialized] + private bool m_ForceClip; + + public Rect canvasRect + { + get + { + Canvas canvas = null; + var list = ListPool.Get(); + gameObject.GetComponentsInParent(false, list); + if (list.Count > 0) + canvas = list[list.Count - 1]; + ListPool.Release(list); + + return m_VertexClipper.GetCanvasRect(rectTransform, canvas); + } + } + + public RectTransform rectTransform + { + get { return m_RectTransform ?? (m_RectTransform = GetComponent()); } + } + + protected RectMask2D() + {} + + protected override void OnEnable() + { + base.OnEnable(); + m_ShouldRecalculateClipRects = true; + ClipperRegistry.Register(this); + MaskUtilities.Notify2DMaskStateChanged(this); + } + + protected override void OnDisable() + { + // we call base OnDisable first here + // as we need to have the IsActive return the + // correct value when we notify the children + // that the mask state has changed. + base.OnDisable(); + m_ClipTargets.Clear(); + m_Clippers.Clear(); + ClipperRegistry.Unregister(this); + MaskUtilities.Notify2DMaskStateChanged(this); + } + +#if UNITY_EDITOR + protected override void OnValidate() + { + base.OnValidate(); + m_ShouldRecalculateClipRects = true; + + if (!IsActive()) + return; + + MaskUtilities.Notify2DMaskStateChanged(this); + } + +#endif + + public virtual bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) + { + if (!isActiveAndEnabled) + return true; + + return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera); + } + + public virtual void PerformClipping() + { + //TODO See if an IsActive() test would work well here or whether it might cause unexpected side effects (re case 776771) + + // if the parents are changed + // or something similar we + // do a recalculate here + if (m_ShouldRecalculateClipRects) + { + MaskUtilities.GetRectMasksForClip(this, m_Clippers); + m_ShouldRecalculateClipRects = false; + } + + // 裁剪 + + // get the compound rects from + // the clippers that are valid + bool validRect = true; + Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect); + bool clipRectChanged = clipRect != m_LastClipRectCanvasSpace; + if (clipRectChanged || m_ForceClip) + { + foreach (IClippable clipTarget in m_ClipTargets) + clipTarget.SetClipRect(clipRect, validRect); + + m_LastClipRectCanvasSpace = clipRect; + m_LastValidClipRect = validRect; + } + + // 剔除 + + foreach (IClippable clipTarget in m_ClipTargets) + { + var maskable = clipTarget as MaskableGraphic; + if (maskable != null && !maskable.canvasRenderer.hasMoved && !clipRectChanged) + continue; + + clipTarget.Cull(m_LastClipRectCanvasSpace, m_LastValidClipRect); + } + } + + public void AddClippable(IClippable clippable) + { + if (clippable == null) + return; + m_ShouldRecalculateClipRects = true; + if (!m_ClipTargets.Contains(clippable)) + m_ClipTargets.Add(clippable); + + m_ForceClip = true; + } + + public void RemoveClippable(IClippable clippable) + { + if (clippable == null) + return; + + m_ShouldRecalculateClipRects = true; + clippable.SetClipRect(new Rect(), false); + m_ClipTargets.Remove(clippable); + + m_ForceClip = true; + } + + protected override void OnTransformParentChanged() + { + base.OnTransformParentChanged(); + m_ShouldRecalculateClipRects = true; + } + + protected override void OnCanvasHierarchyChanged() + { + base.OnCanvasHierarchyChanged(); + m_ShouldRecalculateClipRects = true; + } + + + #region UGUI_DEBUG + + Vector3[] cornors = new Vector3[4]; + + void OnDrawGizmos() + { + Rect rect = rectTransform.rect; + Gizmos.color = Color.red; + rectTransform.GetWorldCorners(cornors); + for (int i = 0; i < cornors.Length; ++i) + { + Gizmos.DrawLine(cornors[i], cornors[(i + 1) % cornors.Length]); + } + } + + #endregion + + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta new file mode 100644 index 0000000..3f31967 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/RectMask2D.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c06d6b758f7cbc148afa25153c439510 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs new file mode 100644 index 0000000..c12f209 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using UnityEngine.Rendering; + +namespace UnityEngine.UI +{ + /// + /// Dynamic material class makes it possible to create custom materials on the fly on a per-Graphic basis, + /// and still have them get cleaned up correctly. + /// + public static class StencilMaterial + { + private class MatEntry + { + public Material baseMat; + public Material customMat; + public int count; + + public int stencilId; + public StencilOp operation = StencilOp.Keep; + public CompareFunction compareFunction = CompareFunction.Always; + public int readMask; + public int writeMask; + public bool useAlphaClip; + public ColorWriteMask colorMask; + } + + private static List m_List = new List(); + + [Obsolete("Use Material.Add instead.", true)] + public static Material Add(Material baseMat, int stencilID) { return null; } + + /// + /// Add a new material using the specified base and stencil ID. + /// + public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction, ColorWriteMask colorWriteMask) + { + return Add(baseMat, stencilID, operation, compareFunction, colorWriteMask, 255, 255); + } + + /// + /// Add a new material using the specified base and stencil ID. + /// + public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction, ColorWriteMask colorWriteMask, int readMask, int writeMask) + { + if ((stencilID <= 0 && colorWriteMask == ColorWriteMask.All) || baseMat == null) + return baseMat; + + if (!baseMat.HasProperty("_Stencil")) + { + Debug.LogWarning("Material " + baseMat.name + " doesn't have _Stencil property", baseMat); + return baseMat; + } + if (!baseMat.HasProperty("_StencilOp")) + { + Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilOp property", baseMat); + return baseMat; + } + if (!baseMat.HasProperty("_StencilComp")) + { + Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilComp property", baseMat); + return baseMat; + } + if (!baseMat.HasProperty("_StencilReadMask")) + { + Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilReadMask property", baseMat); + return baseMat; + } + if (!baseMat.HasProperty("_StencilWriteMask")) + { + Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilWriteMask property", baseMat); + return baseMat; + } + if (!baseMat.HasProperty("_ColorMask")) + { + Debug.LogWarning("Material " + baseMat.name + " doesn't have _ColorMask property", baseMat); + return baseMat; + } + + for (int i = 0; i < m_List.Count; ++i) + { + MatEntry ent = m_List[i]; + + if (ent.baseMat == baseMat + && ent.stencilId == stencilID + && ent.operation == operation + && ent.compareFunction == compareFunction + && ent.readMask == readMask + && ent.writeMask == writeMask + && ent.colorMask == colorWriteMask) + { + ++ent.count; + return ent.customMat; + } + } + + var newEnt = new MatEntry(); + newEnt.count = 1; + newEnt.baseMat = baseMat; + newEnt.customMat = new Material(baseMat); + newEnt.customMat.hideFlags = HideFlags.HideAndDontSave; + newEnt.stencilId = stencilID; + newEnt.operation = operation; + newEnt.compareFunction = compareFunction; + newEnt.readMask = readMask; + newEnt.writeMask = writeMask; + newEnt.colorMask = colorWriteMask; + newEnt.useAlphaClip = operation != StencilOp.Keep && writeMask > 0; + + newEnt.customMat.name = string.Format("Stencil Id:{0}, Op:{1}, Comp:{2}, WriteMask:{3}, ReadMask:{4}, ColorMask:{5} AlphaClip:{6} ({7})", stencilID, operation, compareFunction, writeMask, readMask, colorWriteMask, newEnt.useAlphaClip, baseMat.name); + + newEnt.customMat.SetInt("_Stencil", stencilID); + newEnt.customMat.SetInt("_StencilOp", (int)operation); + newEnt.customMat.SetInt("_StencilComp", (int)compareFunction); + newEnt.customMat.SetInt("_StencilReadMask", readMask); + newEnt.customMat.SetInt("_StencilWriteMask", writeMask); + newEnt.customMat.SetInt("_ColorMask", (int)colorWriteMask); + + // left for backwards compatability + if (newEnt.customMat.HasProperty("_UseAlphaClip")) + newEnt.customMat.SetInt("_UseAlphaClip", newEnt.useAlphaClip ? 1 : 0); + + if (newEnt.useAlphaClip) + newEnt.customMat.EnableKeyword("UNITY_UI_ALPHACLIP"); + else + newEnt.customMat.DisableKeyword("UNITY_UI_ALPHACLIP"); + + m_List.Add(newEnt); + return newEnt.customMat; + } + + /// + /// Remove an existing material, automatically cleaning it up if it's no longer in use. + /// + public static void Remove(Material customMat) + { + if (customMat == null) + return; + + for (int i = 0; i < m_List.Count; ++i) + { + MatEntry ent = m_List[i]; + + if (ent.customMat != customMat) + continue; + + if (--ent.count == 0) + { + Misc.DestroyImmediate(ent.customMat); + ent.baseMat = null; + m_List.RemoveAt(i); + } + return; + } + } + + public static void ClearAll() + { + for (int i = 0; i < m_List.Count; ++i) + { + MatEntry ent = m_List[i]; + + Misc.DestroyImmediate(ent.customMat); + ent.baseMat = null; + } + m_List.Clear(); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta new file mode 100644 index 0000000..3fd6a69 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Mask/StencilMaterial.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d445d28188ffd745990df17f1ce8914 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers.meta new file mode 100644 index 0000000..73eacd4 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 50b4029219e854d4c9407fad9b48266b +folderAsset: yes +timeCreated: 1602119280 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs new file mode 100644 index 0000000..56e4777 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs @@ -0,0 +1,7 @@ +namespace UnityEngine.UI +{ + public interface IMaterialModifier + { + Material GetModifiedMaterial(Material baseMaterial); + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs.meta new file mode 100644 index 0000000..a234594 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/MaterialModifiers/IMaterialModifier.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fff5a5576fa3b2944a873226445ef7ef +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs new file mode 100644 index 0000000..66e2892 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs @@ -0,0 +1,44 @@ +namespace UnityEngine.UI +{ + /// + /// Helper class containing generic functions used throughout the UI library. + /// + + internal static class Misc + { + /// + /// Destroy the specified object, immediately if in edit mode. + /// + + static public void Destroy(UnityEngine.Object obj) + { + if (obj != null) + { + if (Application.isPlaying) + { + if (obj is GameObject) + { + GameObject go = obj as GameObject; + go.transform.parent = null; + } + + Object.Destroy(obj); + } + else Object.DestroyImmediate(obj); + } + } + + /// + /// Destroy the specified object immediately, unless not in the editor, in which case the regular Destroy is used instead. + /// + + static public void DestroyImmediate(Object obj) + { + if (obj != null) + { + if (Application.isEditor) Object.DestroyImmediate(obj); + else Object.Destroy(obj); + } + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs.meta new file mode 100644 index 0000000..51bdc37 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/Misc.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 78074a60b29244441988db79bcd84a23 +timeCreated: 1602119379 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections.meta new file mode 100644 index 0000000..af9c70d --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0402250d11c7a2042bdcab33f69be1a6 +folderAsset: yes +timeCreated: 1602119280 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs new file mode 100644 index 0000000..0f37983 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace UnityEngine.UI.Collections +{ + internal class IndexedSet : IList + { + //This is a container that gives: + // - Unique items + // - Fast random removal + // - Fast unique inclusion to the end + // - Sequential access + //Downsides: + // - Uses more memory + // - Ordering is not persistent + // - Not Serialization Friendly. + + //We use a Dictionary to speed up list lookup, this makes it cheaper to guarantee no duplicates (set) + //When removing we move the last item to the removed item position, this way we only need to update the index cache of a single item. (fast removal) + //Order of the elements is not guaranteed. A removal will change the order of the items. + + readonly List m_List = new List(); + Dictionary m_Dictionary = new Dictionary(); + + public void Add(T item) + { + m_List.Add(item); + m_Dictionary.Add(item, m_List.Count - 1); + } + + public bool AddUnique(T item) + { + if (m_Dictionary.ContainsKey(item)) + return false; + + m_List.Add(item); + m_Dictionary.Add(item, m_List.Count - 1); + + return true; + } + + public bool Remove(T item) + { + int index = -1; + if (!m_Dictionary.TryGetValue(item, out index)) + return false; + + RemoveAt(index); + return true; + } + + public IEnumerator GetEnumerator() + { + throw new System.NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Clear() + { + m_List.Clear(); + m_Dictionary.Clear(); + } + + public bool Contains(T item) + { + return m_Dictionary.ContainsKey(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + m_List.CopyTo(array, arrayIndex); + } + + public int Count { get { return m_List.Count; } } + public bool IsReadOnly { get { return false; } } + public int IndexOf(T item) + { + int index = -1; + m_Dictionary.TryGetValue(item, out index); + return index; + } + + public void Insert(int index, T item) + { + //We could support this, but the semantics would be weird. Order is not guaranteed.. + throw new NotSupportedException("Random Insertion is semantically invalid, since this structure does not guarantee ordering."); + } + + public void RemoveAt(int index) + { + T item = m_List[index]; + m_Dictionary.Remove(item); + if (index == m_List.Count - 1) + m_List.RemoveAt(index); + else + { + int replaceItemIndex = m_List.Count - 1; + T replaceItem = m_List[replaceItemIndex]; + m_List[index] = replaceItem; + m_Dictionary[replaceItem] = index; + m_List.RemoveAt(replaceItemIndex); + } + } + + public T this[int index] + { + get { return m_List[index]; } + set + { + T item = m_List[index]; + m_Dictionary.Remove(item); + m_List[index] = value; + m_Dictionary.Add(item, index); // 这里有问题,应该是value + } + } + + public void RemoveAll(Predicate match) + { + //I guess this could be optmized by instead of removing the items from the list immediatly, + //We move them to the end, and then remove all in one go. + //But I don't think this is going to be the bottleneck, so leaving as is for now. + int i = 0; + while (i < m_List.Count) + { + T item = m_List[i]; + if (match(item)) + Remove(item); + else + i++; + } + } + + //Sorts the internal list, this makes the exposed index accessor sorted as well. + //But note that any insertion or deletion, can unorder the collection again. + public void Sort(Comparison sortLayoutFunction) + { + //There might be better ways to sort and keep the dictionary index up to date. + m_List.Sort(sortLayoutFunction); + //Rebuild the dictionary index. + for (int i = 0; i < m_List.Count; ++i) + { + T item = m_List[i]; + m_Dictionary[item] = i; + } + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs.meta new file mode 100644 index 0000000..942f3d7 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/SpecializedCollections/IndexedSet.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: cfa32e72467bc124294369b8b0b2045e +timeCreated: 1602119380 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls.meta new file mode 100644 index 0000000..4dfd750 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a1494dd81f8d794282718b40b1ea46e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs new file mode 100644 index 0000000..e42871b --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs @@ -0,0 +1,36 @@ +using System; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + [Serializable] + public class AnimationTriggers + { + private const string kDefaultNormalAnimName = "Normal"; + private const string kDefaultSelectedAnimName = "Highlighted"; + private const string kDefaultPressedAnimName = "Pressed"; + private const string kDefaultDisabledAnimName = "Disabled"; + + [FormerlySerializedAs("normalTrigger")] + [SerializeField] + private string m_NormalTrigger = kDefaultNormalAnimName; + + [FormerlySerializedAs("highlightedTrigger")] + [FormerlySerializedAs("m_SelectedTrigger")] + [SerializeField] + private string m_HighlightedTrigger = kDefaultSelectedAnimName; + + [FormerlySerializedAs("pressedTrigger")] + [SerializeField] + private string m_PressedTrigger = kDefaultPressedAnimName; + + [FormerlySerializedAs("disabledTrigger")] + [SerializeField] + private string m_DisabledTrigger = kDefaultDisabledAnimName; + + public string normalTrigger { get { return m_NormalTrigger; } set { m_NormalTrigger = value; } } + public string highlightedTrigger { get { return m_HighlightedTrigger; } set { m_HighlightedTrigger = value; } } + public string pressedTrigger { get { return m_PressedTrigger; } set { m_PressedTrigger = value; } } + public string disabledTrigger { get { return m_DisabledTrigger; } set { m_DisabledTrigger = value; } } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs.meta new file mode 100644 index 0000000..52f2ca0 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/AnimationTriggers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd02e9c578e561646b10984381250bf5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs new file mode 100644 index 0000000..d0c9ae3 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine.Events; +using UnityEngine.EventSystems; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + // Button that's meant to work with mouse or touch-based devices. + [AddComponentMenu("UI/Button", 30)] + public class Button + : Selectable + , IPointerClickHandler // 鼠标点击\触摸 + , ISubmitHandler // Input>Submit触发,比如手柄、键盘某个按键按下 + { + [Serializable] + public class ButtonClickedEvent : UnityEvent {} + + // Event delegates triggered on click. + [FormerlySerializedAs("onClick")] + [SerializeField] + private ButtonClickedEvent m_OnClick = new ButtonClickedEvent(); + + protected Button() + {} + + public ButtonClickedEvent onClick + { + get { return m_OnClick; } + set { m_OnClick = value; } + } + + // 调回调 + private void Press() + { + if (!IsActive() || !IsInteractable()) + return; + + UISystemProfilerApi.AddMarker("Button.onClick", this); + m_OnClick.Invoke(); + } + + // Trigger all registered callbacks. + public virtual void OnPointerClick(PointerEventData eventData) + { + if (eventData.button != PointerEventData.InputButton.Left) + return; + + Press(); + } + + public virtual void OnSubmit(BaseEventData eventData) + { + LogHelper.Log("OnSubmit() " + gameObject.name); + + Press(); + + // if we get set disabled during the press + // don't run the coroutine. + if (!IsActive() || !IsInteractable()) + return; + + DoStateTransition(SelectionState.Pressed, false); + StartCoroutine(OnFinishSubmit()); + } + + private IEnumerator OnFinishSubmit() + { + var fadeTime = colors.fadeDuration; + var elapsedTime = 0f; + + while (elapsedTime < fadeTime) + { + elapsedTime += Time.unscaledDeltaTime; + yield return null; + } + + DoStateTransition(currentSelectionState, false); + } + + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs.meta new file mode 100644 index 0000000..cbdb3a1 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/Button.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a754c749030e1d848bed7a3cb2e5520f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs new file mode 100644 index 0000000..c78d617 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs @@ -0,0 +1,91 @@ +using System; +using UnityEngine.Serialization; + +namespace UnityEngine.UI +{ + [Serializable] + public struct ColorBlock : IEquatable + { + [FormerlySerializedAs("normalColor")] + [SerializeField] + private Color m_NormalColor; + + [FormerlySerializedAs("highlightedColor")] + [FormerlySerializedAs("m_SelectedColor")] + [SerializeField] + private Color m_HighlightedColor; + + [FormerlySerializedAs("pressedColor")] + [SerializeField] + private Color m_PressedColor; + + [FormerlySerializedAs("disabledColor")] + [SerializeField] + private Color m_DisabledColor; + + [Range(1, 5)] + [SerializeField] + private float m_ColorMultiplier; + + [FormerlySerializedAs("fadeDuration")] + [SerializeField] + private float m_FadeDuration; + + public Color normalColor { get { return m_NormalColor; } set { m_NormalColor = value; } } + public Color highlightedColor { get { return m_HighlightedColor; } set { m_HighlightedColor = value; } } + public Color pressedColor { get { return m_PressedColor; } set { m_PressedColor = value; } } + public Color disabledColor { get { return m_DisabledColor; } set { m_DisabledColor = value; } } + public float colorMultiplier { get { return m_ColorMultiplier; } set { m_ColorMultiplier = value; } } + public float fadeDuration { get { return m_FadeDuration; } set { m_FadeDuration = value; } } + + public static ColorBlock defaultColorBlock + { + get + { + var c = new ColorBlock + { + m_NormalColor = new Color32(255, 255, 255, 255), + m_HighlightedColor = new Color32(245, 245, 245, 255), + m_PressedColor = new Color32(200, 200, 200, 255), + m_DisabledColor = new Color32(200, 200, 200, 128), + colorMultiplier = 1.0f, + fadeDuration = 0.1f + }; + return c; + } + } + + public override bool Equals(object obj) + { + if (!(obj is ColorBlock)) + return false; + + return Equals((ColorBlock)obj); + } + + public bool Equals(ColorBlock other) + { + return normalColor == other.normalColor && + highlightedColor == other.highlightedColor && + pressedColor == other.pressedColor && + disabledColor == other.disabledColor && + colorMultiplier == other.colorMultiplier && + fadeDuration == other.fadeDuration; + } + + public static bool operator==(ColorBlock point1, ColorBlock point2) + { + return point1.Equals(point2); + } + + public static bool operator!=(ColorBlock point1, ColorBlock point2) + { + return !point1.Equals(point2); + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } +} diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs.meta b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs.meta new file mode 100644 index 0000000..8680539 --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/ColorBlock.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7d25b8a109dd134fa40749f78bbd907 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/DefaultControls.cs b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/DefaultControls.cs new file mode 100644 index 0000000..a22ff9a --- /dev/null +++ b/Assets/uGUI-2017.1/UnityEngine.UI/UI/Core/UIControls/DefaultControls.cs @@ -0,0 +1,581 @@ +using UnityEngine; +using System.Collections.Generic; + +namespace UnityEngine.UI +{ + public static class DefaultControls + { + public struct Resources + { + public Sprite standard; + public Sprite background; + public Sprite inputField; + public Sprite knob; + public Sprite checkmark; + public Sprite dropdown; + public Sprite mask; + } + + private const float kWidth = 160f; + private const float kThickHeight = 30f; + private const float kThinHeight = 20f; + private static Vector2 s_ThickElementSize = new Vector2(kWidth, kThickHeight); + private static Vector2 s_ThinElementSize = new Vector2(kWidth, kThinHeight); + private static Vector2 s_ImageElementSize = new Vector2(100f, 100f); + private static Color s_DefaultSelectableColor = new Color(1f, 1f, 1f, 1f); + private static Color s_PanelColor = new Color(1f, 1f, 1f, 0.392f); + private static Color s_TextColor = new Color(50f / 255f, 50f / 255f, 50f / 255f, 1f); + + // Helper methods at top + + private static GameObject CreateUIElementRoot(string name, Vector2 size) + { + GameObject child = new GameObject(name); + RectTransform rectTransform = child.AddComponent(); + rectTransform.sizeDelta = size; + return child; + } + + static GameObject CreateUIObject(string name, GameObject parent) + { + GameObject go = new GameObject(name); + go.AddComponent(); + SetParentAndAlign(go, parent); + return go; + } + + private static void SetDefaultTextValues(Text lbl) + { + // Set text values we want across UI elements in default controls. + // Don't set values which are the same as the default values for the Text component, + // since there's no point in that, and it's good to keep them as consistent as possible. + lbl.color = s_TextColor; + + // Reset() is not called when playing. We still want the default font to be assigned + lbl.AssignDefaultFont(); + } + + private static void SetDefaultColorTransitionValues(Selectable slider) + { + ColorBlock colors = slider.colors; + colors.highlightedColor = new Color(0.882f, 0.882f, 0.882f); + colors.pressedColor = new Color(0.698f, 0.698f, 0.698f); + colors.disabledColor = new Color(0.521f, 0.521f, 0.521f); + } + + private static void SetParentAndAlign(GameObject child, GameObject parent) + { + if (parent == null) + return; + + child.transform.SetParent(parent.transform, false); + SetLayerRecursively(child, parent.layer); + } + + private static void SetLayerRecursively(GameObject go, int layer) + { + go.layer = layer; + Transform t = go.transform; + for (int i = 0; i < t.childCount; i++) + SetLayerRecursively(t.GetChild(i).gameObject, layer); + } + + // Actual controls + + public static GameObject CreatePanel(Resources resources) + { + GameObject panelRoot = CreateUIElementRoot("Panel", s_ThickElementSize); + + // Set RectTransform to stretch + RectTransform rectTransform = panelRoot.GetComponent(); + rectTransform.anchorMin = Vector2.zero; + rectTransform.anchorMax = Vector2.one; + rectTransform.anchoredPosition = Vector2.zero; + rectTransform.sizeDelta = Vector2.zero; + + Image image = panelRoot.AddComponent(); + image.sprite = resources.background; + image.type = Image.Type.Sliced; + image.color = s_PanelColor; + + return panelRoot; + } + + public static GameObject CreateButton(Resources resources) + { + GameObject buttonRoot = CreateUIElementRoot("Button", s_ThickElementSize); + + GameObject childText = new GameObject("Text"); + childText.AddComponent(); + SetParentAndAlign(childText, buttonRoot); + + Image image = buttonRoot.AddComponent(); + image.sprite = resources.standard; + image.type = Image.Type.Sliced; + image.color = s_DefaultSelectableColor; + + Button bt = buttonRoot.AddComponent