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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto
19 changes: 19 additions & 0 deletions .github/RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Release checklist

Continuous integration checks what a machine without a GPU can: the tests on the oldest and newest supported Unity, drawn by a software renderer, and player builds for every platform. The rest is checked by hand before each release, most important first.

### Before merging the release pull request

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`.

### After merging

1. Tag the squashed commit on `main` with the version alone, such as `2.0.0`.
2. Export the signed tarball of the package from the Package Manager.
3. Draft the GitHub release from the tag, named like `v2.0.0 (signed)`, with the changelog section as its notes and the tarball attached.
164 changes: 164 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
name: Continuous integration

on:
pull_request:
paths-ignore:
- '**.md'
- '**.jpg'
- '**.png'
push:
branches:
- main
paths-ignore:
- '**.md'
- '**.jpg'
- '**.png'
workflow_dispatch:

# A newer push to the same branch or pull request replaces the run in progress.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
# The test runner reports its results as a check run.
checks: write

# A Personal license needs UNITY_LICENSE, UNITY_EMAIL and UNITY_PASSWORD; a Pro license UNITY_SERIAL instead of the first.
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}

jobs:
tests:
name: Tests on ${{ matrix.unityVersion }}
runs-on: ubuntu-latest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- unityVersion: 2022.3.62f3
# Also compiles and tests the Profiler counters, which exist only with this optional package.
- unityVersion: 6000.5.11f1
optionalPackages: '{"com.unity.profiling.core": "1.0.3"}'
steps:
- name: Free disk space for the Unity image
uses: jlumbroso/free-disk-space@ceedf095f4ec1a097402bc6bd80831f2e1a6fde6 # v2.0.0
with:
large-packages: false

- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

# Without it, Unity takes the project for a new one and adds its template packages to the manifest.
- name: Set the Unity version of the project
env:
UNITY_VERSION: ${{ matrix.unityVersion }}
run: |
mkdir -p UnityProject/ProjectSettings
printf 'm_EditorVersion: %s\n' "$UNITY_VERSION" > UnityProject/ProjectSettings/ProjectVersion.txt

- name: Add the optional packages
if: matrix.optionalPackages
env:
OPTIONAL_PACKAGES: ${{ matrix.optionalPackages }}
run: |
manifest=UnityProject/Packages/manifest.json
jq --argjson packages "$OPTIONAL_PACKAGES" '.dependencies += $packages' "$manifest" > manifest.tmp
mv manifest.tmp "$manifest"

- name: Restore the Library folder
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: UnityProject/Library
key: Library-tests-${{ matrix.unityVersion }}-${{ hashFiles('UnityPackage/**', 'UnityProject/**') }}
restore-keys: Library-tests-${{ matrix.unityVersion }}-

- name: Run the edit and play mode tests
uses: game-ci/unity-test-runner@32e57712352b500e17974b245a6dce9e11a73213 # v4.4.0
env:
# Code coverage crashes play mode tests on Unity 6, see game-ci/unity-test-runner#301. The action's
# coverageEnabled input passes --no-coverageEnabled, which the CLI rejects, so it's turned off here instead.
GAME_CI_COVERAGE_ENABLED: false
with:
unityVersion: ${{ matrix.unityVersion }}
cliVersion: v0.1.69
projectPath: UnityProject
testMode: all
githubToken: ${{ github.token }}
checkName: Test results on ${{ matrix.unityVersion }}

- name: Check that the package compiles without warnings
if: always()
run: |
warnings=$(grep -hs "warning CS" artifacts/*.log | grep -e "com.reromanlee.wireframes" -e "UnityPackage" | sort -u || true)
if [ -n "$warnings" ]; then
echo "$warnings"
echo "::error::The package compiled with warnings."
exit 1
fi

- name: Upload the test results and timings
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: Test results on ${{ matrix.unityVersion }}
path: artifacts

builds:
name: ${{ matrix.targetPlatform }} build on ${{ matrix.unityVersion }}
runs-on: ubuntu-latest
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
include:
# Tier 1 platforms on the oldest and the newest supported Unity.
- { unityVersion: 2022.3.62f3, targetPlatform: WebGL }
- { unityVersion: 2022.3.62f3, targetPlatform: Android }
- { unityVersion: 6000.5.11f1, targetPlatform: WebGL }
- { unityVersion: 6000.5.11f1, targetPlatform: Android }
# Tier 2 platforms, checked to build on the newest Unity.
- { unityVersion: 6000.5.11f1, targetPlatform: iOS }
- { unityVersion: 6000.5.11f1, targetPlatform: StandaloneOSX }
- { unityVersion: 6000.5.11f1, targetPlatform: StandaloneLinux64 }
steps:
- name: Free disk space for the Unity image
uses: jlumbroso/free-disk-space@ceedf095f4ec1a097402bc6bd80831f2e1a6fde6 # v2.0.0
with:
large-packages: false

- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

# Without it, Unity takes the project for a new one and adds its template packages to the manifest.
- name: Set the Unity version of the project
env:
UNITY_VERSION: ${{ matrix.unityVersion }}
run: |
mkdir -p UnityProject/ProjectSettings
printf 'm_EditorVersion: %s\n' "$UNITY_VERSION" > UnityProject/ProjectSettings/ProjectVersion.txt

# Leaves only built-in modules and the local package, so a build never waits on Unity's package registry.
- name: Remove the test-only packages
run: |
manifest=UnityProject/Packages/manifest.json
jq 'del(.dependencies["com.unity.test-framework.performance"]) | del(.testables)' "$manifest" > manifest.tmp
mv manifest.tmp "$manifest"

- name: Add the package samples to the project
run: cp -r UnityPackage/Samples~ UnityProject/Assets/Samples

# Only checks that the player builds; nothing is uploaded or released.
- name: Build the Shape Gallery sample
uses: game-ci/unity-builder@adaf7cd8f42fd48fbbf2d4f5f67ca30d87f819f1 # v5.0.1
with:
unityVersion: ${{ matrix.unityVersion }}
targetPlatform: ${{ matrix.targetPlatform }}
projectPath: UnityProject
buildMethod: reromanlee.Wireframes.ContinuousIntegration.PlayerBuild.Build
versioning: None
108 changes: 61 additions & 47 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,61 @@
# Changelog

All notable changes to this package are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this package adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.0] - 2026-09-24

### Added

- Shapes: polylines (`IPolyline`, created as polylines, polygons or triangles), rectangles, rounded rectangles,
circles, ellipses, stars, spheres, ellipsoids, spiked spheres, cylinders, cones, capsules, stadiums, frustums and
pyramids.
- `IRigidShape`, shared by every shape except lines and polylines: one bone, a local and world position and rotation,
and a `Color`. Changing the bone keeps the shape's world position, rotation and size.
- `IAxialShape`, shared by long shapes: `Length`, and end B through `LocalEnd` and `WorldEnd`.
- Create methods that take bones first and work in their local space, such as `CreateLine(boneA, boneB)` and
`CreateCircle(bone, localCenter, radius)`.
- Polylines have a bone and a color for every point.
- Shape Gallery sample, a scene with every shape. The Stress Test sample spawns every kind of shape.
- `WireframeCamera`, a component that draws everything its camera renders as wireframe, under the Built-in Render
Pipeline or any Scriptable Render Pipeline.

### Changed

- The package lives in the repository's `UnityPackage` folder. Install it from
`https://github.com/reromanlee/Wireframes.git?path=/UnityPackage`.
- Boxes have a center, a rotation and a signed `Size`. Their corner properties still work, and
`CreateBox(center, rotation, size)` creates a rotated box.
- Changing a box's bone keeps its world rotation instead of aligning the box to the new bone's axes.
`CreateBox(bone, localCornerA, localCornerB)` creates a box aligned to a bone.
- `CreateBox()` creates a 1 by 1 by 1 cube instead of a box with both corners at the origin.

## [0.1.0] - 2026-09-22

### Added

- `LineContainer`, which draws all of its shapes with one GPU-skinned mesh. It is disposed by `Dispose()` or when
the scene it was created in unloads, and accepts an optional material.
- Lines (`ILine`) with local and world positions, colors and a bone for each endpoint.
- Boxes (`IBox`) with local and world corners, one bone and `SetColor`.
- `IShape`, shared by every shape: `SetColor`, `Dispose` and `IsDisposed`.
- Shapes whose bone is destroyed stay in place and switch to world space.
- Edits are applied once per frame and upload only what changed.
- Stress Test sample.
- Edit mode and play mode tests.
# Wireframes 2.0.0

### What's new

1. Shapes follow their bones through the package's own shader skinning instead of a `SkinnedMeshRenderer`, which is faster on WebGL and no longer depends on the GPU Skinning player setting.
2. The package's material draws under the Built-in Render Pipeline, URP and HDRP, hides, shows or fades lines behind other geometry through the `Occlusion` setting, and draws transparent colors through `UseAlpha`.
3. Containers and shapes work in Edit Mode, drawing in the Scene and Game views without ever being saved into scenes.
4. Unity 2022.3 is supported, where 1.0 needed Unity 6.
5. `IsVisible` hides a shape or a whole container without disposing it, and without allocating.
6. `WireframeContainerSettings` sets a container's name, material, layer, persistence across scenes, reserved capacity, occlusion and transparency.
7. Containers split shapes into chunks of up to 65,535 vertices with 16-bit indices, hold any number of shapes, and give memory back as shapes are disposed.
8. `container.Statistics` reports shapes, vertices, edges, bones, chunks and memory without allocating, Profiler markers time each step, and Profiler counters add up every container when the `com.unity.profiling.core` package is installed.
9. Server builds, missing shaders, destroyed bones and failing shapes are handled without exceptions reaching Unity's rendering, and each problem is logged once with a `[Wireframes]` prefix.
10. Steady frames allocate nothing and edits upload only what they change, which tests enforce; continuous integration runs the tests on Unity 2022.3 and 6000.5 and builds for WebGL, Android, iOS, macOS and Linux.
11. The README is rewritten, with detailed Features, Performance, Usage and Migration pages in the `Documentation` folder.

### Breaking changes

1. `LineContainer` is now `WireframeContainer`, `ILineContainer` is removed, and a material is passed through `WireframeContainerSettings`.
2. A custom material's shader must move vertices with `WireframesSkin` from the package's `Wireframes.hlsl`.
3. `Segments` and `Sides` are now `SegmentCount` and `SideCount`, and the `segments`, `sides` and star `points` parameters are now `segmentCount`, `sideCount` and `pointCount`.
4. `LocalEnd` and `WorldEnd` of long shapes are now `LocalEndB` and `WorldEndB`, next to the new `LocalEndA` and `WorldEndA`.
5. Edits and bone moves are applied right before each camera renders, instead of at the end of `LateUpdate`.
6. Bones must be Transforms in a scene, and resolutions are capped at 1,024 segments or sides and 512 star points.
7. Calls from other threads throw `InvalidOperationException` in the Editor and development builds.

### Known issues

1. Stereo rendering for XR is untested.

# Wireframes 1.0.0

### What's new

1. New shapes: polylines (`IPolyline`, created as polylines, polygons or triangles), rectangles, rounded rectangles, circles, ellipses, stars, spheres, ellipsoids, spiked spheres, cylinders, cones, capsules, stadiums, frustums and pyramids.
2. `IRigidShape`, shared by every shape except lines and polylines: one bone, a local and world position and rotation, and a `Color`. Changing the bone keeps the shape's world position, rotation and size.
3. `IAxialShape`, shared by long shapes: `Length`, and end B through `LocalEnd` and `WorldEnd`.
4. Create methods that take bones first and work in their local space, such as `CreateLine(boneA, boneB)` and `CreateCircle(bone, localCenter, radius)`.
5. Polylines have a bone and a color for every point.
6. `WireframeCamera`, a component that draws everything its camera renders as wireframe, under the Built-in Render Pipeline or any Scriptable Render Pipeline.
7. The Shape Gallery sample, a scene with every shape, and a Stress Test sample that spawns every kind of shape.

### Changes

1. The package lives in the repository's `UnityPackage` folder; install it from `https://github.com/reromanlee/Wireframes.git?path=/UnityPackage`.
2. Boxes have a center, a rotation and a signed `Size`. Their corner properties still work, and `CreateBox(center, rotation, size)` creates a rotated box.
3. Changing a box's bone keeps its world rotation instead of aligning the box to the new bone's axes; `CreateBox(bone, localCornerA, localCornerB)` creates a box aligned to a bone.
4. `CreateBox()` creates a 1 by 1 by 1 cube instead of a box with both corners at the origin.

# Wireframes 0.1.0

### What's new

1. `LineContainer`, which draws all of its shapes with one GPU-skinned mesh. It is disposed by `Dispose()` or when the scene it was created in unloads, and accepts an optional material.
2. Lines (`ILine`) with local and world positions, colors and a bone for each endpoint.
3. Boxes (`IBox`) with local and world corners, one bone and `SetColor`.
4. `IShape`, shared by every shape: `SetColor`, `Dispose` and `IsDisposed`.
5. Shapes whose bone is destroyed stay in place and switch to world space.
6. Edits are applied once per frame and upload only what changed.
7. The Stress Test sample.
8. Edit Mode and Play Mode tests.
Loading
Loading