Skip to content

Instantly share code, notes, and snippets.

@lowteq
Created January 9, 2020 22:59
Show Gist options
  • Save lowteq/db30c1641c290ffe8f522fe38ac34310 to your computer and use it in GitHub Desktop.
Save lowteq/db30c1641c290ffe8f522fe38ac34310 to your computer and use it in GitHub Desktop.
UnityEditorWindow上で外枠のパスを入力し立体物に変換するスクリプト
using UnityEngine;
using System;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
public class BroochEditor : EditorWindow
{
private class PathTool
{
int selectindex = -1;
DrawTexture2D drawTexture2d = new DrawTexture2D();
Texture2D texture;
bool closed = false;
List<Vector2> veclist;
float r;
int canvasSize;
public PathTool(int canvassize,float radius){
r = radius;
canvasSize = canvassize;
veclist = new List<Vector2>();
texture = new Texture2D(canvasSize,canvasSize);
drawTexture2d = new DrawTexture2D();
}
public Texture2D canvas(){
drawTexture2d.Begin(texture);
drawTexture2d.Clear(new Color(0.0f, 0.0f, 0.0f));
var c = new Color(0.5f, 0.5f, 0.5f);
if (veclist.Count == 0){
drawTexture2d.End();
return texture;
}else{
drawTexture2d.DrawCircle((int)veclist[0].x, (int)veclist[0].y, (int)r, c);
for(var i=1;i<veclist.Count;i++){
var v1 = veclist[i-1];
var v2 = veclist[i];
drawTexture2d.DrawLine((int)v1.x,(int)v1.y,(int)v2.x,(int)v2.y,c);
drawTexture2d.DrawCircle((int)v2.x,(int)v2.y,(int)r,c);
}
}
if(closed){
drawTexture2d.DrawLine((int)veclist[0].x,(int)veclist[0].y,(int)veclist[veclist.Count-1].x,(int)veclist[veclist.Count-1].y,c);
}
drawTexture2d.End();
return texture;
}
public void Clear(){
veclist = new List<Vector2>();
texture = new Texture2D(canvasSize, canvasSize);
drawTexture2d = new DrawTexture2D();
veclist.Clear();
closed = false;
}
public void ReleaseSelect(){
selectindex = -1;
}
public void Move(Vector2 vec)
{
if(selectindex == -1) return;
veclist[selectindex] = vec;
}
public bool Select(Vector2 vec){
selectindex = -1;
for(var i=0;i<veclist.Count;i++){
if(circleIn(vec,veclist[i],r)){
selectindex = i;
return true;
}
}
return false;
}
public bool Add(Vector2 vec){
bool ret = false;
for (var i = 0; i < veclist.Count; i++)
{
if (circleIn(vec, veclist[i], r))
{
//もし追加しようとしてるvecがveclist内の点付近の場合は追加しない
//だたし閉じる処理のveclist[0]のクリックは調べない
if(closed) return false;
}
}
Debug.Log("Pass");
if(closed){
for (var i = 1; i < veclist.Count; i++)
{
if(lineIn(vec,veclist[i-1],veclist[i],r)){
veclist.Insert(i,vec);
Debug.Log("insert 1");
ret = true;
break;
}
}
if (lineIn(vec, veclist[0], veclist[veclist.Count - 1], r))
{
veclist.Insert(0, vec);
Debug.Log("insert 2");
ret = true;
}
}else{
if (veclist.Count > 2)
{
if (circleIn(veclist[0], vec, r))
{
//閉じるための処理
closed = true;
}
else
{
//追加する
veclist.Add(vec);
ret = true;
}
}
else
{
veclist.Add(vec);
ret = true;
}
}
return ret;
}
public void Remove(Vector2 vec){
if(veclist.Count <= 3){
return;
}
for(var i=0;i<veclist.Count;i++){
if (circleIn(veclist[i], vec, r))
{
veclist.RemoveAt(i);
break;
}
}
}
/// <summary>
/// 線分v1-v2上(太さ2*r)にpが存在するか
/// 点v1,v2付近ではfalseになる部分がある
/// </summary>
/// <param name="p"></param>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <param name="r"></param>
/// <returns></returns>
private static bool lineIn(Vector2 p,Vector2 v1,Vector2 v2,float r){
float a = v2.x - v1.x;
float b = v2.y - v1.y;
float a2 = a * a;
float b2 = b * b;
float r2 = a2 + b2;
float tt = -(a*(v1.x-p.x)+b*(v1.y-p.y));
float d2;
if(tt < 0){
d2 = (v1.x-p.x)*(v1.x-p.x) + (v1.y-p.y)*(v1.y-p.y);
}
if(tt > r2){
d2 = (v2.x-p.x)*(v2.x-p.x) + (v2.y-p.y)*(v2.y-p.y);
}
float f1 = a*(v1.y-p.y)-b*(v1.x-p.x);
d2 = (f1*f1)/r2;
Debug.Log(Math.Sqrt(d2));
if (d2<=r && dist2(v1,p) < r2 && dist2(v2,p) < r2){
return true;
}else{
return false;
}
}
/// <summary>
/// 2点間の距離の2乗
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
private static float dist2(Vector2 p1,Vector2 p2){
float c =(p2.x - p1.x);
float d =(p2.y - p1.y);
return c*c + d*d;
}
private static bool circleIn(Vector2 mousevec, Vector2 plotvec, float r)
{
if (Math.Pow(mousevec.x - plotvec.x, 2) + Math.Pow(mousevec.y - plotvec.y, 2) <= r * r)
{
return true;
}
else
{
return false;
}
}
}
Texture2D texture = null;
private int canvasOffsetX = 240;
private int canvasOffsetY = 20;
private int canvasSize = 500;
private int selGridInt = 0;
private PathTool pt;
enum ToolType{
AddEdit = 0,Remove = 1
}
private string[] selCaptions = new string[] {
"Add/Edit",
"Remove",
};
[MenuItem("Window/BroochEditor")]
private static void Create()
{
// 生成
var window = GetWindow<BroochEditor>("Brooch Editor");
window.minSize = new Vector2(320, 320);
window.Init();
}
private void Init(){
pt = new PathTool(canvasSize, 5);
}
void OnInspectorUpdate()
{
if (EditorWindow.focusedWindow == this &&
EditorWindow.mouseOverWindow == this)
{
this.Repaint();
}
}
public static void SetTextureImporterFormat(Texture2D texture, bool isReadable)
{
if (texture.isReadable == isReadable){
return;
}
string assetPath = AssetDatabase.GetAssetPath(texture);
var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (tImporter != null)
{
//tImporter.textureType = TextureImporterType.Default;
tImporter.isReadable = isReadable;
AssetDatabase.ImportAsset(assetPath);
AssetDatabase.Refresh();
}
}
void OnGUI()
{
Event e = Event.current;
var cmp = new Vector2(e.mousePosition.x - canvasOffsetX,e.mousePosition.y - canvasOffsetY);
if(0< cmp.x && cmp.x < canvasSize && 0 < cmp.y && cmp.y < canvasSize){
CanvasBehaviour(e,cmp);
}
EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(200));{
EditorGUILayout.BeginVertical(GUI.skin.box);{
EditorGUILayout.BeginVertical(GUI.skin.box);
{
var mp = e.mousePosition;
EditorGUILayout.LabelField("x:" + mp.x + " y:" + mp.y + " type:" + e.type);
if (e.type == EventType.MouseDown){
Debug.Log(mp);
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical(GUI.skin.box);{
EditorGUI.BeginChangeCheck();
texture = EditorGUILayout.ObjectField("Reference Texture:", texture, typeof(Texture), false) as Texture2D;
if(EditorGUI.EndChangeCheck()){
Debug.Log("ChangeTexture");
if (texture != null){
SetTextureImporterFormat(texture,true);
}
}
}EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical(GUI.skin.box);{
EditorGUILayout.LabelField("Tools",EditorStyles.boldLabel);
selGridInt = GUILayout.SelectionGrid(selGridInt, selCaptions, 1, EditorStyles.radioButton);
}EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical(GUI.skin.box);{
GUILayout.Label("Base Settings", EditorStyles.boldLabel);
// myString = EditorGUILayout.TextField("Text Field", myString);
}EditorGUILayout.EndVertical();
}EditorGUILayout.EndVertical();
}
if (texture != null)
{
// Color[] pixels = texture.GetPixels();
// Color[] change_pixels = new Color[pixels.Length];
// for (int i = 0; i < pixels.Length; i++)
// {
// Color pixel = pixels[i];
// // 書き換え用テクスチャのピクセル色を指定
// Color change_pixel = new Color(1f, pixel.g, pixel.b, pixel.a);
// change_pixels.SetValue(change_pixel, i);
// }
// // 書き換え用テクスチャの生成
// Texture2D change_texture = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
// change_texture.filterMode = FilterMode.Point;
// change_texture.SetPixels(change_pixels);
// change_texture.Apply();
//EditorGUI.DrawPreviewTexture(new Rect(240,20, 500, 500),texture);
}
}
private void CanvasBehaviour(Event e,Vector2 canvasMousePosition){
// if((ToolType)selGridInt==ToolType.Add){
// switch(e.type){
// case EventType.MouseDown:
// pt.Add(canvasMousePosition);
// break;
// }
// }
if((ToolType)selGridInt==ToolType.Remove){
switch(e.type){
case EventType.MouseDown:
pt.Remove(canvasMousePosition);
break;
}
}else if((ToolType)selGridInt==ToolType.AddEdit){
switch(e.type){
case EventType.MouseDown:
if(!pt.Add(canvasMousePosition)){
pt.Select(canvasMousePosition);
}
break;
case EventType.MouseDrag:
pt.Move(canvasMousePosition);
break;
case EventType.MouseUp:
pt.ReleaseSelect();
break;
}
}
var drawtex = pt.canvas();
EditorGUI.DrawPreviewTexture(new Rect(240,20,500,500),drawtex);
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment