├── .codacy.yml ├── .github └── FUNDING.yml ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── Documentation~ └── ConstrainedRect.md ├── Editor.meta ├── Editor ├── Constrain.cs ├── Constrain.cs.meta ├── ConstrainedRect.cs ├── ConstrainedRect.cs.meta ├── ConstrainedRectPool.cs ├── ConstrainedRectPool.cs.meta ├── Constraint.cs ├── Constraint.cs.meta ├── InvalidStateException.cs ├── InvalidStateException.cs.meta ├── TNRD.ConstrainedRect.Editor.asmdef └── TNRD.ConstrainedRect.Editor.asmdef.meta ├── LICENSE.md ├── LICENSE.md.meta ├── README.md ├── README.md.meta ├── Tests.meta ├── Tests ├── Editor.meta └── Editor │ ├── ConstrainedRectTests.cs │ ├── ConstrainedRectTests.cs.meta │ ├── TNRD.ConstrainedRect.Editor.Tests.asmdef │ └── TNRD.ConstrainedRect.Editor.Tests.asmdef.meta ├── package.json └── package.json.meta /.codacy.yml: -------------------------------------------------------------------------------- 1 | exclude_paths: 2 | - '*.md' 3 | - '*.json' -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: thundernerd 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [3.0.2] - 2020-10-17 4 | ### Added 5 | - Extra download option 6 | 7 | ### Updated 8 | - Author name 9 | 10 | ## [3.0.1] - 2020-08-02 11 | ### Fixed 12 | - Resetting of horizontal and vertical centering 13 | 14 | ## [3.0.0] - 2020-08-02 15 | ### Added 16 | - Pooling of Constrained Rect 17 | 18 | ## [2.1.0] - 2020-06-07 19 | ### Added 20 | - Options to center horizontally and vertically 21 | 22 | ## [2.0.2] - 2020-02-19 23 | ### Fixed 24 | - Incorrect naming of assembly definitions 25 | 26 | ## [2.0.1] - 2020-02-19 27 | ### Fixed 28 | - Tests assembly references 29 | 30 | ## [2.0.0] - 2020-02-17 31 | ### Added 32 | - Tests 33 | 34 | ### Changed 35 | - Calculation method for left, top, right, bottom 36 | - Width and height no longer override right and bottom by default 37 | 38 | ## [1.0.0] - 2020-02-16 39 | ### Added 40 | - Initial version 41 | -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b895e7cd6288d094499ac018fdd101ef 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Documentation~/ConstrainedRect.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Thundernerd/Unity3D-ConstrainedRect/1c9d4b8d404b64ae4a0c0afe57c76090277b423c/Documentation~/ConstrainedRect.md -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c266a3a42ee4aa540853ee6ac0fefc5a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Constrain.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace TNRD.Constraints 5 | { 6 | public static class Constrain 7 | { 8 | public static ConstrainedRect To(EditorWindow editorWindow) 9 | { 10 | return To(new Rect(Vector2.zero, editorWindow.position.size)); 11 | } 12 | 13 | public static ConstrainedRect To(Rect rect) 14 | { 15 | return ConstrainedRectPool.Create(rect); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Editor/Constrain.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1699fa6aa709e6740bd556dd5db4083a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ConstrainedRect.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace TNRD.Constraints 4 | { 5 | public class ConstrainedRect 6 | { 7 | private Rect parent; 8 | 9 | public Constraint Top { get; } 10 | public Constraint Bottom { get; } 11 | public Constraint Left { get; } 12 | public Constraint Right { get; } 13 | public Constraint Width { get; } 14 | public Constraint Height { get; } 15 | 16 | private bool centerHorizontally; 17 | private bool centerVertically; 18 | 19 | private bool isValid; 20 | 21 | internal ConstrainedRect(Rect parent) 22 | { 23 | Top = new Constraint(this, false); 24 | Bottom = new Constraint(this, true); 25 | Left = new Constraint(this, false); 26 | Right = new Constraint(this, true); 27 | Width = new Constraint(this, false); 28 | Height = new Constraint(this, false); 29 | 30 | Reset(parent); 31 | } 32 | 33 | internal void Reset(Rect parent) 34 | { 35 | this.parent = parent; 36 | 37 | centerHorizontally = false; 38 | centerVertically = false; 39 | 40 | Top.Reset(); 41 | Bottom.Reset(); 42 | Left.Reset(); 43 | Right.Reset(); 44 | Width.Reset(); 45 | Height.Reset(); 46 | 47 | isValid = true; 48 | } 49 | 50 | public Rect Relative(float value) 51 | { 52 | ThrowIfInvalid(); 53 | return Relative(value, value, value, value); 54 | } 55 | 56 | public Rect Relative(float left, float top, float right, float bottom) 57 | { 58 | ThrowIfInvalid(); 59 | return Left.Relative(left) 60 | .Top.Relative(top) 61 | .Right.Relative(right) 62 | .Bottom.Relative(bottom) 63 | .ToRect(); 64 | } 65 | 66 | public ConstrainedRect CenterHorizontally() 67 | { 68 | ThrowIfInvalid(); 69 | centerHorizontally = true; 70 | return this; 71 | } 72 | 73 | public ConstrainedRect CenterVertically() 74 | { 75 | ThrowIfInvalid(); 76 | centerVertically = true; 77 | return this; 78 | } 79 | 80 | public Rect ToRect() 81 | { 82 | ThrowIfInvalid(); 83 | float left, top, right, bottom; 84 | 85 | CalculateHorizontal(out left, out right); 86 | CalculateVertical(out top, out bottom); 87 | 88 | ConstrainedRectPool.Return(this); 89 | isValid = false; 90 | 91 | return new Rect(left, top, right, bottom); 92 | } 93 | 94 | private void CalculateHorizontal(out float left, out float right) 95 | { 96 | if (centerHorizontally && Width.IsSet) 97 | { 98 | float width = Mathf.Abs(Width.RawValue); 99 | left = parent.center.x - width * 0.5f; 100 | right = width; 101 | 102 | return; 103 | } 104 | 105 | if (!Width.IsSet || (Left.IsSet && Right.IsSet)) 106 | { 107 | left = Left.Apply(parent.xMin); 108 | right = Right.Apply(parent.xMax) - left; 109 | return; 110 | } 111 | 112 | if (Left.IsSet && !Right.IsSet) 113 | { 114 | left = Left.Apply(parent.xMin); 115 | right = Width.Apply(parent.width); 116 | } 117 | else if (!Left.IsSet && Right.IsSet) 118 | { 119 | right = Width.Apply(parent.width); 120 | left = Right.Apply(parent.xMax) - right; 121 | } 122 | else 123 | { 124 | left = Left.Apply(parent.xMin); 125 | right = Width.Apply(parent.width); 126 | } 127 | } 128 | 129 | private void CalculateVertical(out float top, out float bottom) 130 | { 131 | if (centerVertically && Height.IsSet) 132 | { 133 | float height = Mathf.Abs(Height.RawValue); 134 | top = parent.center.y - height * 0.5f; 135 | bottom = height; 136 | 137 | return; 138 | } 139 | 140 | if (!Height.IsSet || (Top.IsSet && Bottom.IsSet)) 141 | { 142 | top = Top.Apply(parent.yMin); 143 | bottom = Bottom.Apply(parent.yMax) - top; 144 | return; 145 | } 146 | 147 | if (Top.IsSet && !Bottom.IsSet) 148 | { 149 | top = Top.Apply(parent.yMin); 150 | bottom = Height.Apply(parent.height); 151 | } 152 | else if (!Top.IsSet && Bottom.IsSet) 153 | { 154 | bottom = Height.Apply(parent.height); 155 | top = Bottom.Apply(parent.yMax) - bottom; 156 | } 157 | else 158 | { 159 | top = Top.Apply(parent.yMin); 160 | bottom = Height.Apply(parent.height); 161 | } 162 | } 163 | 164 | internal void ThrowIfInvalid() 165 | { 166 | if (isValid) 167 | return; 168 | 169 | throw new InvalidStateException(); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Editor/ConstrainedRect.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 15fa1a9cc2a642e99f5033c8a46b1c8f 3 | timeCreated: 1581849896 -------------------------------------------------------------------------------- /Editor/ConstrainedRectPool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace TNRD.Constraints 5 | { 6 | internal static class ConstrainedRectPool 7 | { 8 | private static List available = new List(); 9 | 10 | public static ConstrainedRect Create(Rect to) 11 | { 12 | if (available.Count == 0) 13 | { 14 | return CreateNew(to); 15 | } 16 | 17 | var constrainedRect = available[0]; 18 | available.Remove(constrainedRect); 19 | constrainedRect.Reset(to); 20 | return constrainedRect; 21 | } 22 | 23 | private static ConstrainedRect CreateNew(Rect to) 24 | { 25 | var constrainedRect = new ConstrainedRect(to); 26 | return constrainedRect; 27 | } 28 | 29 | public static void Return(ConstrainedRect constrainedRect) 30 | { 31 | available.Add(constrainedRect); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Editor/ConstrainedRectPool.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c20fcfc87224074988a6248fe27f678 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Constraint.cs: -------------------------------------------------------------------------------- 1 | namespace TNRD.Constraints 2 | { 3 | public class Constraint 4 | { 5 | private enum ConstrainMode 6 | { 7 | NotSet, 8 | Relative, 9 | Absolute, 10 | Percentage 11 | } 12 | 13 | private readonly ConstrainedRect parent; 14 | private readonly bool negateValue; 15 | private ConstrainMode mode; 16 | private float value; 17 | 18 | private float Value => negateValue ? -value : value; 19 | 20 | internal float RawValue => value; 21 | 22 | public bool IsSet => mode != ConstrainMode.NotSet; 23 | 24 | internal Constraint(ConstrainedRect parent, bool negateValue) 25 | { 26 | this.parent = parent; 27 | this.negateValue = negateValue; 28 | Reset(); 29 | } 30 | 31 | internal void Reset() 32 | { 33 | mode = ConstrainMode.NotSet; 34 | value = 0; 35 | } 36 | 37 | public ConstrainedRect Relative(float value) 38 | { 39 | parent.ThrowIfInvalid(); 40 | mode = ConstrainMode.Relative; 41 | this.value = value; 42 | return parent; 43 | } 44 | 45 | public ConstrainedRect Absolute(float value) 46 | { 47 | parent.ThrowIfInvalid(); 48 | mode = ConstrainMode.Absolute; 49 | this.value = value; 50 | return parent; 51 | } 52 | 53 | public ConstrainedRect Percentage(float value) 54 | { 55 | parent.ThrowIfInvalid(); 56 | mode = ConstrainMode.Percentage; 57 | this.value = value; 58 | return parent; 59 | } 60 | 61 | internal float Apply(float value) 62 | { 63 | parent.ThrowIfInvalid(); 64 | switch (mode) 65 | { 66 | case ConstrainMode.Relative: 67 | return value + Value; 68 | case ConstrainMode.Absolute: 69 | return this.value; // We don't want to negate the value here 70 | case ConstrainMode.Percentage: 71 | return value * Value; 72 | } 73 | 74 | return value; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Editor/Constraint.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3575745fc998d943ae476af06b72c09 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/InvalidStateException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TNRD.Constraints 4 | { 5 | public class InvalidStateException : Exception 6 | { 7 | public InvalidStateException() 8 | : base("The Constrained Rect that you're trying to modify has already been pooled and is no longer available for usage") 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Editor/InvalidStateException.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 388be25e30464ee5aca7991b06b68e49 3 | timeCreated: 1596396726 -------------------------------------------------------------------------------- /Editor/TNRD.ConstrainedRect.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TNRD.ConstrainedRect.Editor", 3 | "references": [], 4 | "includePlatforms": [ 5 | "Editor" 6 | ], 7 | "excludePlatforms": [], 8 | "allowUnsafeCode": false, 9 | "overrideReferences": false, 10 | "precompiledReferences": [], 11 | "autoReferenced": true, 12 | "defineConstraints": [], 13 | "versionDefines": [], 14 | "noEngineReferences": false 15 | } -------------------------------------------------------------------------------- /Editor/TNRD.ConstrainedRect.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6c5cf85c5f3b0f41844e3ea4b956783 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Christiaan Bloemendaal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8f76fe6fa175ed458a0b3f9ab2e8d94 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Constrained Rect 2 | 3 |

4 | GitHub package.json version 5 | 6 | GitHub issues 7 | 8 | 9 | GitHub pull requests 10 | 11 | 12 | GitHub license 13 | 14 | GitHub last commit 15 |

16 | 17 | Constrained Rect is a small helper that aims to make it easier to create Rect's based on existing ones. 18 | 19 | ## Installation 20 | 1. The package is available on the [openupm registry](https://openupm.com). You can install it via [openupm-cli](https://github.com/openupm/openupm-cli). 21 | ``` 22 | openupm add net.tnrd.constrainedrect 23 | ``` 24 | 2. Installing through a [Unity Package](http://package-installer.glitch.me/v1/installer/package.openupm.com/net.tnrd.constrainedrect?registry=https://package.openupm.com) created by the [Package Installer Creator](https://package-installer.glitch.me) from [Needle](https://needle.tools) 25 | 26 | [](http://package-installer.glitch.me/v1/installer/package.openupm.com/net.tnrd.constrainedrect?registry=https://package.openupm.com) 27 | 28 | 3. You can also install via git url by adding these entries in your **manifest.json** 29 | ```json 30 | "net.tnrd.constrainedrect": "https://github.com/Thundernerd/Unity3D-ConstrainedRect.git" 31 | ``` 32 | 33 | 34 | ## Usage 35 | Using constrained rects is easy. You simply call `Constrain.To(...)` and pass it either a `Rect` or an `EditorWindow`. 36 | 37 | 38 | Here's an example using a simple Rect 39 | ```csharp 40 | private void Foo() 41 | { 42 | Rect rect = new Rect(16, 16, 128, 128); 43 | 44 | Rect constrainedRect = Constrain.To(rect) 45 | .Left.Relative(8) 46 | .Top.Relative(16) 47 | .Right.Relative(24) 48 | .Bottom.Relative(32) 49 | .ToRect(); 50 | 51 | Debug.Log(constrainedRect.xMin); // Logs 24 52 | Debug.Log(constrainedRect.yMin); // Logs 32 53 | Debug.Log(constrainedRect.xMax); // Logs 104 54 | Debug.Log(constrainedRect.yMax); // Logs 96 55 | } 56 | ``` 57 | 58 | Aside from `Left`, `Top`, `Right`, and `Bottom`, you can also use `Width` and `Height`. If you want to use `width` and `height` you will have to omit either `left` or `right` and `top` or `bottom` respectively. 59 | 60 | Other modifiers are `Absolute` and `Percentage`. 61 | Absolute is what it suggests: instead of taking into account it's constraints it just returns the value given. 62 | 63 | Percentage expects a float value between 0 and 1 (inclusive) and multiplies that value with the constrained property. 64 | ```csharp 65 | private void Foo() 66 | { 67 | Rect rect = new Rect(16, 16, 128, 128); 68 | 69 | Rect constrainedRect = Constrain.To(rect) 70 | .Width.Percentage(0.5f) 71 | .ToRect(); 72 | 73 | Debug.Log(constrainedRect.width); // Logs 64 74 | } 75 | ``` 76 | 77 | ### Important 78 | Due to the nature of Unity's editor architecture it is common to use Constrained Rects in high volume. In an attempt to prevent creating and collecting too much garbage as a result of using Constrained Rects they are now being pooled. 79 | 80 | After you've finalized your Constrained Rect by calling `.ToRect()` the Constrained Rect will be returned to the pool and free to use for other instances. 81 | 82 | While all of this happens under the hood it is important to understand that from the moment that you call `.ToRect()` the Constrained Rect will throw an exception if it is not being used. This also means that if it is being used then the properties and variables might be different from what you might expect. 83 | 84 | ## Support 85 | **Constrained Rect** is a small and open-source utility that I hope helps other people. It is by no means necessary but if you feel generous you can support me by donating. 86 | 87 | [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/J3J11GEYY) 88 | 89 | ## Contributing 90 | Pull requests are welcomed. Please feel free to fix any issues you find, or add new features. 91 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6df8bcef14f7ddf4bab9d5757ad63056 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a4803b604f0f26643ac5600c143c16a6 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ba6c684bd8fa9d4f91bb267cef209a9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Editor/ConstrainedRectTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using UnityEngine; 3 | 4 | namespace TNRD.Constraints.Tests 5 | { 6 | [TestFixture] 7 | internal class ConstrainedRectTests 8 | { 9 | private Rect rect; 10 | 11 | [SetUp] 12 | public void SetUp() 13 | { 14 | rect = new Rect(0, 0, 128, 128); 15 | } 16 | 17 | [Test] 18 | public void Relative() 19 | { 20 | var constrained = Constrain.To(rect) 21 | .Relative(8); 22 | 23 | Assert.AreEqual(8, constrained.xMin); 24 | Assert.AreEqual(8, constrained.yMin); 25 | Assert.AreEqual(120, constrained.xMax); 26 | Assert.AreEqual(120, constrained.yMax); 27 | } 28 | 29 | [Test] 30 | public void Absolute() 31 | { 32 | var constrained = Constrain.To(rect) 33 | .Left.Absolute(8) 34 | .Top.Absolute(8) 35 | .Right.Absolute(16) 36 | .Bottom.Absolute(16) 37 | .ToRect(); 38 | 39 | Assert.AreEqual(8, constrained.xMin); 40 | Assert.AreEqual(8, constrained.yMin); 41 | Assert.AreEqual(16, constrained.xMax); 42 | Assert.AreEqual(16, constrained.yMax); 43 | } 44 | 45 | [Test] 46 | public void TopLeftRelative() 47 | { 48 | var constrained = Constrain.To(rect) 49 | .Top.Relative(8) 50 | .Left.Relative(8) 51 | .ToRect(); 52 | 53 | Assert.AreEqual(8, constrained.xMin); 54 | Assert.AreEqual(8, constrained.yMin); 55 | } 56 | 57 | [Test] 58 | public void BottomRightRelative() 59 | { 60 | var constrained = Constrain.To(rect) 61 | .Bottom.Relative(8) 62 | .Right.Relative(8) 63 | .ToRect(); 64 | 65 | Assert.AreEqual(120, constrained.xMax); 66 | Assert.AreEqual(120, constrained.yMax); 67 | } 68 | 69 | [Test] 70 | public void LeftWidthRelative() 71 | { 72 | var constrained = Constrain.To(rect) 73 | .Left.Relative(8) 74 | .Width.Relative(-8) 75 | .ToRect(); 76 | 77 | Assert.AreEqual(8, constrained.xMin); 78 | Assert.AreEqual(120, constrained.width); 79 | } 80 | 81 | [Test] 82 | public void LeftWidthPercentage() 83 | { 84 | var constrained = Constrain.To(rect) 85 | .Left.Relative(8) 86 | .Width.Percentage(0.5f) 87 | .ToRect(); 88 | 89 | Assert.AreEqual(8, constrained.xMin); 90 | Assert.AreEqual(64, constrained.width); 91 | } 92 | 93 | [Test] 94 | public void RightWidthRelative() 95 | { 96 | var constrained = Constrain.To(rect) 97 | .Right.Relative(8) 98 | .Width.Relative(-8) 99 | .ToRect(); 100 | 101 | Assert.AreEqual(120, constrained.xMax); 102 | Assert.AreEqual(120, constrained.width); 103 | } 104 | 105 | [Test] 106 | public void RightWidthPercentage() 107 | { 108 | var constrained = Constrain.To(rect) 109 | .Right.Relative(8) 110 | .Width.Percentage(0.5f) 111 | .ToRect(); 112 | 113 | Assert.AreEqual(120, constrained.xMax); 114 | Assert.AreEqual(64, constrained.width); 115 | } 116 | 117 | [Test] 118 | public void TopHeightRelative() 119 | { 120 | var constrained = Constrain.To(rect) 121 | .Top.Relative(8) 122 | .Height.Relative(-8) 123 | .ToRect(); 124 | 125 | Assert.AreEqual(8, constrained.yMin); 126 | Assert.AreEqual(120, constrained.height); 127 | } 128 | 129 | [Test] 130 | public void TopHeightPercentage() 131 | { 132 | var constrained = Constrain.To(rect) 133 | .Top.Relative(8) 134 | .Height.Percentage(0.5f) 135 | .ToRect(); 136 | 137 | Assert.AreEqual(8, constrained.yMin); 138 | Assert.AreEqual(64, constrained.height); 139 | } 140 | 141 | [Test] 142 | public void BottomHeightRelative() 143 | { 144 | var constrained = Constrain.To(rect) 145 | .Bottom.Relative(8) 146 | .Height.Relative(-8) 147 | .ToRect(); 148 | 149 | Assert.AreEqual(120, constrained.yMax); 150 | Assert.AreEqual(120, constrained.height); 151 | } 152 | 153 | [Test] 154 | public void BottomHeightPercentage() 155 | { 156 | var constrained = Constrain.To(rect) 157 | .Bottom.Relative(8) 158 | .Height.Percentage(0.5f) 159 | .ToRect(); 160 | 161 | Assert.AreEqual(120, constrained.yMax); 162 | Assert.AreEqual(64, constrained.height); 163 | } 164 | 165 | [Test] 166 | public void CenterHorizontally() 167 | { 168 | var constrained = Constrain.To(rect) 169 | .Width.Absolute(20) 170 | .CenterHorizontally() 171 | .ToRect(); 172 | 173 | Assert.AreEqual(20, constrained.width); 174 | Assert.AreEqual(128 / 2 - 10, constrained.xMin); 175 | Assert.AreEqual(128 / 2 + 10, constrained.xMax); 176 | } 177 | 178 | [Test] 179 | public void CenterVertically() 180 | { 181 | var constrained = Constrain.To(rect) 182 | .Height.Absolute(20) 183 | .CenterVertically() 184 | .ToRect(); 185 | 186 | Assert.AreEqual(20, constrained.height); 187 | Assert.AreEqual(128 / 2 - 10, constrained.yMin); 188 | Assert.AreEqual(128 / 2 + 10, constrained.yMax); 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /Tests/Editor/ConstrainedRectTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d4dac40be8d23ac40bb596c3a555d66b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Editor/TNRD.ConstrainedRect.Editor.Tests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TNRD.ConstrainedRect.Editor.Tests", 3 | "references": [ 4 | "UnityEditor.TestRunner", 5 | "TNRD.ConstrainedRect.Editor" 6 | ], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": true, 13 | "precompiledReferences": [ 14 | "nunit.framework.dll" 15 | ], 16 | "autoReferenced": false, 17 | "defineConstraints": [], 18 | "versionDefines": [], 19 | "noEngineReferences": false 20 | } -------------------------------------------------------------------------------- /Tests/Editor/TNRD.ConstrainedRect.Editor.Tests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c0e05c3b962a3e84cb7fe69ffc292dfa 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "net.tnrd.constrainedrect", 3 | "version": "3.0.2", 4 | "displayName": "Constrained Rect", 5 | "description": "A simple helper to constrain a Rect to an EditorWindow or another Rect", 6 | "unity": "2019.1", 7 | "keywords": [ 8 | "rect", 9 | "editor", 10 | "help", 11 | "helper" 12 | ], 13 | "author": { 14 | "name": "TNRD", 15 | "email": "unity3d@tnrd.net", 16 | "url": "https://www.tnrd.net" 17 | }, 18 | "dependencies": {} 19 | } 20 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eedb9b20993f863498db4324534e54fc 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------