Code Monkey home page Code Monkey logo

shapeeditor's Introduction

2D Shape Editor for Unity.

The 2D Shape Editor is a versatile tool to create complex 3D meshes out of 2D shapes.

With this program you can easily create a design cross-section in a two-dimensional view and then expand it to a 3D mesh.

Default 2D Shape Editor Window

This tool has been integrated directly into the Unity editor to ensure a seamless and fast workflow. When you need a special design, such as curved pipes, an underground channel or a baroque arch, this is the tool for the job.

The controls and user interface were inspired by the popular modeling program Blender. Many of the shortcuts and tricks also work in this program. Special tools have been provided to allow a non-destructive workflow with generators that can be easily modified.

YouTube 2D Shape Editor for Unity - Getting Started

Constructive Solid Geometry:

The shape editor can generate boolean brushes for constructive solid geometry. These brushes let you add and subtract arbitrary shapes to quickly create walls and rooms or cut out doors and windows.

It automatically detects and supports RealtimeCSG and Chisel Editor by using convex decomposition to create multiple convex brushes that accurately represent the concave shape.

Installation Instructions:

Add the following line to your Unity Package Manager:

Unity Package Manager

https://github.com/Henry00IS/ShapeEditor.git

Support:

Feel free to join my Discord server and let's talk about it.

If you found this package useful, please consider making a donation or supporting me on Patreon. Your donations are a tremendous encouragement for the continued development and support of this package. ๐Ÿ˜

Support me on Patreon

paypal

shapeeditor's People

Contributors

gawidev avatar henry00is avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

shapeeditor's Issues

Assign materials to segments and shapes

Have a list of materials in the project. The user can assign materials to individual segments as well as the entire shape. The segments will be shown with a different color to indicate the material slot used. Subtractive shapes can be represented using dotted lines where additive shapes will have filled lines as usual. The materials assigned to the segments are used for the extruded sides of the mesh and materials assigned to the shapes themselves are used for the front and back faces of the mesh.

This will make it more user-friendly to change and extrude the same brush later in RealtimeCSG, as this way at least the materials are kept between updates. It also makes the regular meshes more useful. Requires #5.

Knife tool

Knife tool where you can draw a line to cut a shape into two shapes. In Blender that's keyboard shortcut K.

How do we handle modifiers? Apply them? Warn the user first "One or more shapes will be applied"? Only apply the modifiers that get cut? The user can simply undo the damage with CTRL+Z so perhaps asking is unnecessary.

[50$ Bounty] Create RealtimeCSG Brush from PolygonMesh

Background

In RealtimeCSG, brushes (convex meshes) are represented using the half-edge data structure (see here).

At the moment we convert all of the polygons of a generated convex mesh into planes and then feed those into a RealtimeCSG function that converts a set of planes into a brush. But converting planes (finding the intersection point of 3 planes, where sometimes there are infinite intersections) into a convex mesh is a difficult problem. That's why it often fails and has stability problems.

Your task

Build a function that can take a PolygonMesh (see here) and build a brush in the scene, by calling
BrushFactory.CreateBrush (see here). This requires generating the half-edge connectivity data.

Files

The C# function has been prepared and only needs contents. Here is a special version of the 2D Shape Editor that you can add as a package:

com.aeternumgames.shapeeditor.zip

Here is the Bounty.cs file, place this file in your RealtimeCSG installation (in your Assets directory):

RealtimeCSGBounty.zip

Try extruding using "RealtimeCSG -> Create Bevel" and you will get a notification in the console window that leads you to the function that needs to be written.

public static CSGBrush CreateBrushFromPolygonMesh(Transform parent, string brushName, PolygonMesh mesh)
{
	var controlMesh = new ControlMesh();
	var shape = new Shape();

	Debug.Log("Bounty code goes here! Thank you! <3");
	return BrushFactory.CreateBrush(parent, brushName, controlMesh, shape);
}

Tips

  • A PolygonMesh is just a List of Polygon. They are convex n-gons (no triangulation) without duplicate normals.
  • The payment of 50$ (or 50โ‚ฌ if preferred) will be made via PayPal after verifying your work.

Scrollable GuiList Control

Build a scrollable GuiList control that can display a list of GuiListItem with the ability to drag and drop order them around. Every GuiListItem should be able to hold regular controls. This list can then be used for a visual list of all shapes in the project and a list of materials etc. If the scrolling logic is stand-alone, like GuiScrollableContainer, it could then be used to scroll the contents of any window or control. This would be the preferred approach to implementing this as that could for example turn multiple inspector windows into one scrollable context-sensitive window.

Measuring tape tool

A measuring tape that lets you place two points on the grid and then shows the distance between them.

Tooltips sometimes don't disappear

Tooltips should disappear when the shape editor loses focus. It's been hard to find a way to reproduce the issue where tooltips show up outside of the shape editor window. Can it happen while the shape editor still has window focus?

2DSE tooltip on the scene view

Input numbers for scaling and rotation while dragging

Just like Blender, allow the user to type numbers while scaling, rotating or translating as a multiplier.

I already wrote the code for a simple keyboard recorder. The problem has been finding an elegant way to add this to tools without having to copy and paste the logic everywhere. Something almost as simple as a C# property for the tools that support this feature (or an input focus related thing).

#if UNITY_EDITOR

using System;
using UnityEditor;
using UnityEngine;

namespace AeternumGames.ShapeEditor
{
    /// <summary>Processes keyboard numbers for typing multipliers during active tools and widgets.</summary>
    [Serializable]
    public class NumericKeyboardRecorder
    {
        /// <summary>The accumulated string of characters.</summary>
        private string accumulator = "";

        private float lastValidFloat = 0.0f;

        /// <summary>Gets or sets (clears) whether the user has typed a value using the keyboard.</summary>
        public bool hasValue
        {
            get
            {
                if (accumulator.Length == 0) return false;

                return true;
            }
            set
            {
                if (!value)
                    Reset();
            }
        }

        /// <summary>The last valid value typed assuming <see cref="hasValue"/> is true.</summary>
        public float value => lastValidFloat;

        /// <summary>The text typed assuming <see cref="hasValue"/> is true.</summary>
        public string text => accumulator;

        /// <summary>Must be called on key down events.</summary>
        public bool OnKeyDown(KeyCode keyCode)
        {
            var character = (char)keyCode;

            // add floating point related characters to the accumulator.
            if (ValidateCharacter(character))
            {
                accumulator += character;
                UpdateValue();
                return true;
            }

            if (hasValue)
            {
                // backspace can be used to remove the last character.
                if (keyCode == KeyCode.Backspace)
                {
                    OnBackspace();
                    UpdateValue();
                    return true;
                }

                // minus can be used to negate the number.
                if (keyCode == KeyCode.Minus)
                {
                    OnMinus();
                    UpdateValue();
                    return true;
                }
            }

            return false;
        }

        // whitelist the input characters related to floating point numbers.
        private bool ValidateCharacter(char character)
        {
            switch (character)
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                case '.':
                    return true;
            }
            return false;
        }

        private void OnBackspace()
        {
            if (accumulator.Length == 0) return;
            accumulator = accumulator.Remove(accumulator.Length - 1, 1);
        }

        private void OnMinus()
        {
            if (accumulator.ContainsInvarianCulture("-"))
                accumulator = accumulator.Replace("-", "");
            else
                accumulator = "-" + accumulator;
        }

        private void UpdateValue()
        {
            if (ExpressionEvaluator.Evaluate(accumulator, out float number))
                lastValidFloat = number;
        }

        /// <summary>Resets the current input.</summary>
        public void Reset()
        {
            accumulator = "";
            lastValidFloat = 0.0f;
        }
    }
}

#endif

Bridge edges

Allow the user to select an edge on two shapes and bridge the gap with a new shape between them.

Two shapes with an edge selected

A new selected shape appears between those edges

Draw Tool

With an existing edge selected, a vertex will be inserted on that edge and it will follow the mouse cursor. Click to place it and you will be dragging around the next vertex. Press enter to confirm (and discard the last vertex) or confirm with a precise click at the last vertex. The user can cancel the operation with the escape key.

Without any selection, you will see a vertex that follows the mouse cursor. Click to place it and you will be dragging around the next vertex. Press enter to confirm (and discard the last vertex) or confirm with a precise click at the last vertex. Obviously there will have to be at least 3 placed vertices, until that is the case ignore the enter key and let the user exit with the escape key.

Revolve extrude with zero radius

Using Revolve Extrude with a Radius of 0 generates a degenerative quad in the center. This then causes errors in RealtimeCSG.

Desired Result, shows a cylinder with degrees set to 360 degrees

Flipping shapes is unpredictable in the moment

Perhaps there should be a pivot to flip against or some other fancy tool that makes it clear what's going to happen. Right now you have little control and the shape will appear to move around almost arbitrarily during the flip. Scaling by negative one -1 just like Blender with #8 could also improve this issue.

[50$ Bounty] PolyBool can cause an editor crash on T-Junctions

Two shapes that look like a B

Boolean operations mistakenly consider these two shapes as a single shape with an infinitely thin point connecting them, causing the convex decomposition to fail. This will then cause a stack overflow and editor crash in the BayazitDecomposer. The splitting of this type of polygon at the singularity has yet to be fixed.

It's likely that PolyBoolJS (and thus PolyBoolCS) has this as an oversight in their algorithm. They scan lines vertically and end up merging them together. Maybe this is correct in their eyes. But we need a way to detect and split these singularities into multiple shapes. Whether you fix it here as a post-process or there in the core algorithm, it would be an incredible achievement and I will be super thankful!

Example Projects: S2D Projects Bad.zip

The payment of 50$ (or 50โ‚ฌ if preferred) will be made via PayPal after verifying your work.

Apply mirrored shapes

When using symmetry it would be nice to be able to apply the mirrored shapes (insert them as regular shapes). Perhaps through the shape inspector window.

Only the top of the fish has been modelled, the bottom is a mirror image

Translate and Scale constraints do not react immediately

Pressing X or Y during a translate or scale operation to activate the constraints, will not modify the selection until you move the mouse. It should happen immediately upon activation. Preferably with as little code changed as possible.

Zooming limit because the editor can get unresponsive

Have a limit to the amount the user can zoom in and out, preferably the maximum amounts we can get away with in both directions, before the program fails to pan vertically and horizontally (among other issues).

Ability to flip arch lines at will

Adding an option to invert the direction of an arch line segment whenever you want, possibly through a bool in the arch inspector.

Also at the moment when flipping a shape, the arch directions aren't flipped along with the rest, leaving them pointing out in the opposite direction.

Render rotated text

For the measuring tool, it would be good if text could be rendered on an angle to follow the measuring line.

Create CSG brushes near zero for added precision

Brushes are built in 3D at their destination position (local space of the extrude target). The further you move away from zero the worse the floating point accuracy gets. This will eventually cause small faces to appear between brushes:

Faces in a subtractive hole made by multiple brushes

Building brushes near zero and then moving them to their destination could improve the stability.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.