click to draw polys

Hello all

I’m attempting to draw closed polygons by clicking to create handles and then connecting them with lines. I have got as far as continuous connected lines, but have no idea of how to close the shape and start a new one. Can someone please help… I have a hangover and my brain hurts. 8)

This code instantiates the handles, which are numbered sequentially using an instance counter. What I need is, if I click on the first instance (“name0”), then the line is connected from the current instance to the very first instance, thus closing the loop. From then on, the new instances should have a different name and the numbering should start from 0 again, so I can create another polygon.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class HandleCount : MonoBehaviour
{
    public GameObject handle;
    //Container for GameObjects
    GameObject[] Container;
    GameObject instance;    
    //List of instances
    List<GameObject> GOList = new List<GameObject>();  
    void Start()
    {
    Container = new GameObject[1] {handle};
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) {
        	Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        	RaycastHit hit;
        if (Physics.Raycast (ray, out hit)) { 
        if(hit.collider.gameObject.tag.Contains("plane")) {
            
            for (int i = 0; i <= 0; i++) {
                
                foreach (GameObject objectt in Container) {                 
                    {   
                            instance = (GameObject)Instantiate(objectt, hit.point, transform.rotation);
                            instance.name = "name" + GOList.Count.ToString();
                        //Add instance to the List
                        GOList.Add(instance);
                        //Set index of the instance
                        instance.GetComponent<InstanceCounter>().i = GOList.Count;                      
                    	}
                	}
            	}
        	}
        	
    	}
	}
}
}

This is the instance counter code added to the handle prefab. The prefab also needs to have a LineRenderer attached (obviously).

using UnityEngine;
using System.Collections;

public class InstanceCounter : MonoBehaviour
{
    //Instance Number
    public int i;
}

And this is the handles code, also connected to the handle prefab.

var receiver: Transform;
var myname : String;
var number : String;
var mynumber : int;

function Update () {            
      myname = this.gameObject.name;
      number = myname.Replace("name","");
      mynumber = parseInt(number) +1;
      receiver = GameObject.Find("name" + mynumber).transform;
      var line : LineRenderer = GetComponent(LineRenderer); 
      line.SetPosition(0, transform.position); 
      line.SetPosition(1, receiver.position);
}

If you have Unity Pro you have access to the GL class which is a low level rendering class. It looks like it works a lot like programming for OpenGL, but I have not used the class myself. You might do something like store an array of Vector3 objects of where your vertices are use that data to produce you a set of polygons. If you want to read more on it you can go here Unity - Scripting API: GL

I have no idea how or even if you can create polygons in the free Unity since you would not have access to that class, but if someone else knows then I’m sure they will help you out.

I don’t have pro unfortunately.

But perhaps I didn’t explain myself very clearly. I am drawing a polygon in a sense of a multisided shape made from lines, not as a polygon mesh. So really it’s the closing of the shape, completing it, that’s the problem.

Thanks for the advice though.

Check how far the latest click is from the first point created (you can do this with Vector3.Distance) and consider the shape closed if the two points are sufficiently close together.

The easiest way to start a new shape is to add the single shape drawing script to a prefab and then create a new instance of it whenever you detect the shape is closed. If you disable the script on the current object, it won’t keep adding new points:-

if (closed) {
   Instantiate(drawingPrefab);
   this.enabled = false;
}

I foresee a problem with this, because another piece of code still needs to continue working on the same instance. So if I disable the targeting code, I’m afraid the code that moves the handles around, thus altering the polygon’s shape won’t function anymore.

Also the shape really needs to be closed, so effectively the first handle becomes the last handle. I tried scripting it so when a button is clicked the first handle becomes the target, but all that did was connect all the other handles’ lines to it, not just the second-to-last ones.

Just in case someone stumbles on this thread, here is my solution.

The first two bits of code goe on a prefab of a handle object (in my case a simple cube).

var receiver : Transform;
var first : boolean;
var h_count : int;

function Update () {	
	  h_count = GameObject.Find("Editor").GetComponent("HandleEditor").h_count - 1;
      first = GameObject.Find("Editor").GetComponent("HandleEditor").first;
    if (first){
	if (gameObject.name.Equals("Handle0")){
		receiver = GameObject.Find("Handle" + h_count).transform;
	}
    }
	else{		                
      var id = GetComponent("Handle").id - 1;
      receiver = GameObject.Find("Handle" + id).transform; 
      
	}
      var line : LineRenderer = GetComponent(LineRenderer); 
      line.SetPosition(0, transform.position); 
      line.SetPosition(1, receiver.position);
}

This one too…

using UnityEngine;
using System.Collections;

public class Handle : MonoBehaviour {
	
	public static ArrayList handles = new ArrayList ();
	public int id;
	
	public static void reset () {
		handles = new ArrayList ();
	}
	
	public static void InitAll () {
		Handle handle;
		handles.Sort ();
		for (int i = 0; i < handles.Count; i++) {
			handle = (Handle)handles[i];

		}
	}
	
	public void Awake () {
		handles.Add(this);

	}
}

Meanwhile this code goes on an empty game object in the scene.

using UnityEngine;
using System.Collections;

public class HandleEditor : MonoBehaviour {

private static bool first = false;
private static int h_count = 0;
public GameObject handle;

	void Update () {
		
		if (Input.GetMouseButtonUp (0)) {
			Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            RaycastHit hit;
		
			if (Physics.Raycast (ray, out hit)) {
            if (hit.collider.gameObject.name.Equals("Handle0")) { 
            first = true;
            this.enabled = false;       		
		}
		else {
			first = false;
		}
			
		    if (hit.collider.gameObject.name.Equals("Plane")) {
			
			UnityEngine.Object[] handles = FindObjectsOfType(typeof(Handle));
	        h_count = handles.Length;
					
			GameObject handleInstance = Instantiate(handle, hit.point, Quaternion.identity) as GameObject;
			handleInstance.name = "Handle" + h_count.ToString("0");
			Handle handleScript = handleInstance.GetComponent("Handle") as Handle;
			handleScript.id = h_count;
			h_count++; 		    
		}
		}
	}
    }
}

Hope it helps someone.