Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ Continuous integration checks what a machine without a GPU can: the tests on the
1. Every check of the pull request passes: the tests on both Unity versions, and the WebGL, Android, iOS, macOS and Linux builds.
2. The whole test suite passes locally on a real GPU, on the oldest and the newest supported Unity.
3. The Stress Test sample runs smoothly in Windows, Android and WebGL builds, with frame, main thread and GPU times no worse than the previous release's.
4. The Shape Gallery sample and all three occlusion modes look right on the same devices, in the Built-in, URP and HDRP pipelines.
5. A Profiler capture of an Android development build under load shows no new spikes in the `Wireframes.*` markers and no allocations in steady frames.
6. The timings in the test results artifacts are no worse than the previous release's.
7. `package.json` has the new version, `CHANGELOG.md` has its section, and the README and `Documentation/` describe the release; a major release also updates `Documentation/MIGRATION.md`.
4. Both scenes of the Shape Gallery sample and all three occlusion modes look right on the same devices, in the Built-in, URP and HDRP pipelines.
5. In the Editor, under each pipeline, shape components draw in the Scene and Game views and in Prefab Mode, Draw As Gizmo shapes show only in the Scene view and in the Game view with Gizmos on, and clicking a wireframe never selects a hidden container.
6. A Profiler capture of an Android development build under load shows no new spikes in the `Wireframes.*` markers and no allocations in steady frames.
7. The timings in the test results artifacts are no worse than the previous release's.
8. `package.json` has the new version, `CHANGELOG.md` has its section, and the README and `Documentation/` describe the release; a major release also updates `Documentation/MIGRATION.md`.

### After merging

Expand Down
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
# Wireframes (Unreleased)

### What's new

1. Shape components draw a shape on their GameObject without code, in Edit Mode, Play Mode and builds: **Add Component > Wireframes** has one for every shape, such as `WireframeSphere` and `WireframeLine`.
2. Every change to a component shows up in the next render, made in the Inspector, by undo, animation or a script, and components do no work per frame.
3. Disabling a component or its GameObject hides its shape at no cost, and enabling it again allocates nothing.
4. Components share containers by occlusion, transparency and layer, so many of them draw in a few draw calls; a color with alpha below 1 draws transparent, and shapes draw on their GameObject's layer.
5. `DrawAsGizmo` draws a component's shape like a gizmo, in the Scene view and in the Game view while its Gizmos button is on, and builds leave it out.
6. Prefab Mode draws the components of the prefab being edited.
7. The Shape Gallery sample has a ComponentGallery scene made of components, and continuous integration builds it too.
8. A container without shapes skips its work before each render once its empty chunks are released.

### Known issues

1. The Hierarchy's Scene visibility toggles don't hide components' wireframes, and the Gizmos menu's per-component checkboxes don't affect gizmo shapes.
2. Clicking a component's wireframe in the Scene view doesn't select its GameObject.
3. A script that changes a GameObject's layer moves its components' shapes to that layer on their next change.
4. Stereo rendering for XR is untested.

# Wireframes 2.0.0

### What's new
Expand Down
56 changes: 35 additions & 21 deletions Documentation/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,42 @@ A shape attaches to Transforms, called bones, and moves, turns and scales with t

### 17 shapes

| Shape | Usual Create method | What it is |
|---|---|---|
| `ILine` | `CreateLine(a, b)` | A segment; each end has its own bone. |
| `IPolyline` | `CreatePolyline(points)`, `CreatePolygon(points)`, `CreateTriangle(a, b, c)` | Points joined in order, open or closed; each point has its own bone and color. |
| `IBox` | `CreateBox(cornerA, cornerB)` | A box with a center, a rotation and a `Size`. |
| `IRectangle` | `CreateRectangle(cornerA, cornerB)` | A flat rectangle. |
| `IRoundedRectangle` | `CreateRoundedRectangle(cornerA, cornerB, cornerRadius)` | A flat rectangle with round corners. |
| `ICircle` | `CreateCircle(center, radius)` | A flat circle; `CreateCircle(center, normal, radius)` faces a direction. |
| `IEllipse` | `CreateEllipse(tipA, tipB, radius)` | A flat ellipse whose long axis runs between two tips. |
| `IStar` | `CreateStar(center, innerRadius, outerRadius, pointCount)` | A flat star. |
| `ISphere` | `CreateSphere(center, radius)` | Three great circles. |
| `IEllipsoid` | `CreateEllipsoid(tipA, tipB, radius)` | Three ellipses, with a radius along each axis. |
| `ISpikedSphere` | `CreateSpikedSphere(center, baseRadius, spikeLength, spikeCount)` | A 3D star: a Platonic solid with a spike on each face, so 4, 6, 8, 12 or 20 spikes. |
| `ICylinder` | `CreateCylinder(endA, endB, radius)` | Two rings joined by four lines. |
| `ICone` | `CreateCone(tip, baseCenter, radius)` | A base ring joined to the tip by four lines. |
| `ICapsule` | `CreateCapsule(centerA, centerB, radius)` | Two spheres wrapped together, like `Physics.CapsuleCast`; each end can have its own radius. |
| `IStadium` | `CreateStadium(centerA, centerB, radius)` | The flat outline of a capsule. |
| `IFrustum` | `CreateFrustum(endA, endB, radiusA, radiusB, sideCount)` | Two regular polygons joined at every corner. Prisms and regular pyramids are frustums too. |
| `IPyramid` | `CreatePyramid(tip, baseCenter, baseSize)` | A rectangular base joined to a tip, like a camera's view without its near plane. |
| Shape | Usual Create method | Component | What it is |
|---|---|---|---|
| `ILine` | `CreateLine(a, b)` | `WireframeLine` | A segment; each end has its own bone. |
| `IPolyline` | `CreatePolyline(points)`, `CreatePolygon(points)`, `CreateTriangle(a, b, c)` | `WireframePolyline` | Points joined in order, open or closed; each point has its own bone and color. |
| `IBox` | `CreateBox(cornerA, cornerB)` | `WireframeBox` | A box with a center, a rotation and a `Size`. |
| `IRectangle` | `CreateRectangle(cornerA, cornerB)` | `WireframeRectangle` | A flat rectangle. |
| `IRoundedRectangle` | `CreateRoundedRectangle(cornerA, cornerB, cornerRadius)` | `WireframeRoundedRectangle` | A flat rectangle with round corners. |
| `ICircle` | `CreateCircle(center, radius)` | `WireframeCircle` | A flat circle; `CreateCircle(center, normal, radius)` faces a direction. |
| `IEllipse` | `CreateEllipse(tipA, tipB, radius)` | `WireframeEllipse` | A flat ellipse whose long axis runs between two tips. |
| `IStar` | `CreateStar(center, innerRadius, outerRadius, pointCount)` | `WireframeStar` | A flat star. |
| `ISphere` | `CreateSphere(center, radius)` | `WireframeSphere` | Three great circles. |
| `IEllipsoid` | `CreateEllipsoid(tipA, tipB, radius)` | `WireframeEllipsoid` | Three ellipses, with a radius along each axis. |
| `ISpikedSphere` | `CreateSpikedSphere(center, baseRadius, spikeLength, spikeCount)` | `WireframeSpikedSphere` | A 3D star: a Platonic solid with a spike on each face, so 4, 6, 8, 12 or 20 spikes. |
| `ICylinder` | `CreateCylinder(endA, endB, radius)` | `WireframeCylinder` | Two rings joined by four lines. |
| `ICone` | `CreateCone(tip, baseCenter, radius)` | `WireframeCone` | A base ring joined to the tip by four lines. |
| `ICapsule` | `CreateCapsule(centerA, centerB, radius)` | `WireframeCapsule` | Two spheres wrapped together, like `Physics.CapsuleCast`; each end can have its own radius. |
| `IStadium` | `CreateStadium(centerA, centerB, radius)` | `WireframeStadium` | The flat outline of a capsule. |
| `IFrustum` | `CreateFrustum(endA, endB, radiusA, radiusB, sideCount)` | `WireframeFrustum` | Two regular polygons joined at every corner. Prisms and regular pyramids are frustums too. |
| `IPyramid` | `CreatePyramid(tip, baseCenter, baseSize)` | `WireframePyramid` | A rectangular base joined to a tip, like a camera's view without its near plane. |

Every shape except lines and polylines also has a Create method on a bone, in its local space, one from a position and a rotation, and one without arguments for a white shape of unit size. Round shapes are drawn like Unity's gizmos, with rings and a few lines, from 3 to 1,024 segments per ring.

### Shape components

Every shape has a component that draws it on its GameObject without any code, the same in Edit Mode, Play Mode and builds.

1. The shape follows its GameObject's Transform like a mesh, scale included. Rigid shapes take a `Center` and a `Rotation` relative to it, or for long shapes the two ends of their axis and a `Roll` around it; points of lines and polylines can follow other Transforms.
2. Every change shows up in the next render, made in the Inspector, by undo, a prefab revert, animation or a script. Components do no work per frame, so a moving GameObject costs nothing more than a moving bone.
3. Disabling a component, or its GameObject, hides its shape and costs nothing, and enabling it again allocates nothing.
4. Components share containers, one per combination of occlusion, transparency, layer and gizmo drawing, so hundreds of them draw in a few draw calls. A color with alpha below 1 draws transparent, and a shape draws on its GameObject's layer.
5. `DrawAsGizmo` draws a shape like a gizmo: in the Scene view, and in the Game view only while its Gizmos button is on. Builds leave such shapes out.
6. Prefab Mode draws the components of the prefab being edited, in its own scene.
7. Counts that runtime shapes fix at creation, such as `SegmentCount`, can change on a component, which creates its shape again.

The Hierarchy's Scene visibility toggles don't hide components' wireframes, and the Gizmos menu's per-component checkboxes don't affect gizmo shapes.

### Edits upload only what they change

A setter only records the change, and each edited shape is written once per frame however many of its properties changed. Only the changed ranges of the GPU buffers are uploaded, and moving bones uploads nothing but their matrices. Tests check that editing one shape among many uploads that shape alone.
Expand All @@ -49,7 +63,7 @@ Frames that move bones, edit shapes, hide and show them, or change nothing alloc
A `WireframeContainer` creates and draws shapes, and disposes them when it is disposed or when the scene it was created in unloads. `WireframeContainerSettings` chooses how, and is serializable, so a script can show it in the Inspector.

| Setting | Default | What it does |
|---|---|---|
|---|---|---|---|
| `Occlusion` | `Hide` | What is drawn of lines that other geometry hides: nothing, everything, or a dimmer line. |
| `UseAlpha` | false | Blends each color by its alpha instead of drawing opaque lines. |
| `Material` | none | Draws with your material instead of the package's. |
Expand All @@ -74,7 +88,7 @@ Shapes are stored in chunks, meshes of up to 65,535 vertices with 16-bit indices

### Play Mode, Edit Mode and builds

Containers and shapes work the same in Edit Mode, drawing in the Scene and Game views. There, a container is never saved into its scene and never marks it as changed; it is disposed before scripts reload and when its scene closes, unless it persists across scenes. Switching between Edit and Play Mode alone never disposes a container.
Containers and shapes work the same in Edit Mode, drawing in the Scene and Game views. There, a container is never saved into its scene and never marks it as changed; it is disposed before scripts reload and when its scene closes, unless it persists across scenes. Switching between Edit and Play Mode alone never disposes a container. Shape components draw in Edit Mode as soon as they are added.

### Visibility

Expand Down
38 changes: 37 additions & 1 deletion Documentation/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,42 @@ public sealed class BoundsPreview : MonoBehaviour
2. It is disposed before scripts reload, after which Unity calls `OnEnable` again, and when its scene closes, unless it persists across scenes.
3. Switching between Edit and Play Mode alone never disposes a container, though the script reload that Play Mode starts with by default does.

### Components

To draw a shape without writing code, add its component to a GameObject: **Add Component > Wireframes** has one for every shape, from **Line** to **Pyramid**. It draws there right away, in Edit Mode, Play Mode and builds, and follows the GameObject's Transform like a mesh, scale included. Its fields place the shape relative to the GameObject:

| Components | Place the shape with |
|---|---|
| `WireframeBox`, `WireframeRectangle`, `WireframeRoundedRectangle`, `WireframeCircle`, `WireframeEllipse`, `WireframeStar`, `WireframeSphere`, `WireframeEllipsoid`, `WireframeSpikedSphere` | **Center** and **Rotation**, in Euler angles. Flat shapes lie flat on the GameObject with no rotation. |
| `WireframeCylinder`, `WireframeCone`, `WireframeCapsule`, `WireframeStadium`, `WireframeFrustum`, `WireframePyramid` | **End A** and **End B**, the ends of the shape's axis, and **Roll** around it. A cone's or pyramid's tip is end A. With no roll, the shape's +Y stays as close to the GameObject's up as the axis allows. |
| `WireframeLine`, `WireframePolyline` | A **Bone** and a **Position** for each point: the point follows that Transform, or the GameObject when it has none. |

1. **Every change shows up in the next render,** made in the Inspector, by undo, a prefab revert, animation or a script. A count that runtime shapes fix at creation, such as **Segment Count**, creates the shape again, once you finish typing it, and invalid counts snap to the nearest valid one.
2. **`enabled` shows and hides the shape.** Disabling the component or its GameObject costs nothing, and enabling it again allocates nothing.
3. **One color per shape.** **Color** colors all of it, and an alpha below 1 draws it transparent; **Occlusion** works like the container setting. Shapes draw on their GameObject's layer, for camera culling masks.
4. **Draw As Gizmo** draws the shape like a gizmo: in the Scene view, and in the Game view only while its **Gizmos** button is on. Other cameras never draw it, and builds leave it out. To leave out a whole GameObject meant for debugging, tag it **EditorOnly**, which strips it from builds with its children.
5. **A destroyed bone counts as none,** so its point follows the GameObject from the next render on. A bone has to be in a scene: one that isn't, such as a prefab asset, is reported once and the GameObject followed instead.
6. **New components draw what the Create methods without arguments draw,** relative to the GameObject: a white shape of unit size, with long shapes running 1 unit along +Z. A line runs 1 unit forward, and a polyline starts as a small triangle; it draws nothing with fewer than 2 points, or 3 when closed.

Scripts set the same properties, and counts outside their range throw `ArgumentOutOfRangeException`, as Create methods do:

```csharp
WireframeLine line = gameObject.AddComponent<WireframeLine>();
line.BoneB = target;
line.PositionB = Vector3.up;
line.Color = Color.cyan;

WireframeSphere sphere = gameObject.AddComponent<WireframeSphere>();
sphere.Radius = 2f;
sphere.Occlusion = WireframeOcclusion.Show;
```

Components share containers, one per combination of occlusion, transparency, layer and **Draw As Gizmo**, so many components draw in a few draw calls. Those containers are never saved, stay out of the Hierarchy, and go away with their last component. Prefab Mode draws the components of the prefab being edited in its own scene.

1. The Hierarchy's Scene visibility toggles don't hide components' wireframes, and the per-component checkboxes of the **Gizmos** menu don't affect gizmo shapes.
2. A script that changes `gameObject.layer` moves the shape to that layer on the component's next change; a change in the Inspector moves it at once.
3. Clicking a wireframe in the Scene view doesn't select its GameObject.

### Custom materials

A custom material draws a container when its shader moves vertices with `WireframesSkin` from the package's include file. Each vertex arrives relative to its bone, with the bone's index in `TEXCOORD0`, and the package sets the `_WireframesBones` texture on every renderer. `WireframesColor` converts vertex colors in linear color space, as the package's shader does.
Expand Down Expand Up @@ -183,7 +219,7 @@ Add the **WireframeCamera** component to a Camera to draw everything that camera

Import them from the package's **Samples** tab in the Package Manager.

1. **Shape Gallery** lays out every shape in three rows, each turning with its own bone. Open its **ShapeGallery** scene and enter Play Mode.
1. **Shape Gallery** lays out every shape in three rows, each turning with its own bone. Open its **ShapeGallery** scene and enter Play Mode. Its **ComponentGallery** scene has the same shapes made of components, drawn as soon as it opens, and turning in Play Mode.
2. **Stress Test** spawns 10,000 lines, 1,000 boxes and 2,000 other shapes on 100 orbiting bones. Add the `StressTest` component to an empty GameObject in a scene with a camera, and enter Play Mode with the Profiler open. Raise **Recolor Per Frame** to measure the cost of edits.

### Tests
Expand Down
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ Wireframe shapes for Unity that follow Transforms on the GPU: create a shape onc

Lines, polylines, boxes, circles, spheres, capsules, cones and more attach to any Transforms, called bones. The package uploads each bone's matrix once per frame and the vertex shader moves every vertex, so moving shapes cost your code nothing and an edit uploads only what it changed.

Without writing code, add a shape component to a GameObject: it draws there at once, in Edit Mode too, and shows every change to its fields as you make it.

Shapes draw the same in Play Mode, Edit Mode and player builds, under the Built-in Render Pipeline, URP and HDRP, from desktops and phones to WebGL, while server builds keep them working without drawing.

### Features

1. Shapes follow Transforms on the GPU.
2. 17 shapes, from lines to capsules.
3. Edits upload only what they change.
4. Steady frames allocate nothing.
5. Built-in Render Pipeline, URP and HDRP.
6. Windows, Android, WebGL and more.
7. Play Mode, Edit Mode and builds.
8. Hidden lines hide, show or fade.
9. Shapes hide without being disposed.
10. Statistics and Profiler markers.
11. Destroyed bones leave shapes in place.
12. A camera that draws in wireframe.
3. Shape components, edited live in Edit Mode.
4. Edits upload only what they change.
5. Steady frames allocate nothing.
6. Built-in Render Pipeline, URP and HDRP.
7. Windows, Android, WebGL and more.
8. Play Mode, Edit Mode and builds.
9. Hidden lines hide, show or fade.
10. Shapes hide without being disposed.
11. Statistics and Profiler markers.
12. Destroyed bones leave shapes in place.
13. A camera that draws in wireframe.

Detailed about features - see [FEATURES.md](Documentation/FEATURES.md).

Expand Down Expand Up @@ -107,6 +110,8 @@ sphere.Radius = 2f;
sphere.IsVisible = false;
```

**Or add a shape component to a GameObject, with no code at all.** **Add Component > Wireframes** has one for every shape, from **Line** to **Pyramid**. It draws on its GameObject right away, in Edit Mode, Play Mode and builds, follows it like a mesh, and shows each change to its fields in the next render; disabling it hides the shape.

Detailed about usage - see [USAGE.md](Documentation/USAGE.md).

### License
Expand Down
Loading
Loading