//
//	２点を指定して面を分割する
//
function SeparatePolygons()
{
	var	point[2];
	var	key;
	var	sel, sels, work_sel;
	var	vers, i, j, k;
	var	flag, temp;
	var	pick, draw_flag = ON;
	var	v[MAXVERTEX];

	if( SelectPolygons() == 0 )
	{
		Warning();
		if( MESSAGE == ON )
			Message( error_msg3 );
		return;
	}
	sel = Select();

	point[0] = Cursor();
	SelectArea( TRUE, SELECT_AND | SELECT_SUB, point[0], point[0] );
	work_sel = Select();
	if( SelectPolygons() == 0 )
	{
		Warning();
		Select( sel );
		if( MESSAGE == ON )
		{
			temp = PolyVertex( point[0] );
			if( temp == point[0] )
				Message( error_msg2 );
			else
				Message( error_msg1 );
		}
		return;
	}
	Select( sel );

	PushMenu();
	Status_org = Status_title;
	MenuPosition( Menu( " 動作設定(&S)",
			"分割中止	ESC",	MenuQuit
		), Menu_Title );
	ClearStatus();
	Status_title[0] = "【面分割中】";
	DrawStatus();

	quit_flag = FALSE;

	cur = Cursor();
	pick = cur;
	input_flag = OFF;
	while( TRUE )
	{
		if( draw_flag == ON )
			DrawLine( point[0], cur );
		key = WaitEvent();
		if( key )
			input_flag = ON;
		if( ( ShiftStat() & 1 ) == 1 )
		{
			cur = Cursor();
			TrimCursor(point[0], MouseWindow());
			Cursor( cur );
		}
		else
			cur = Cursor();
		key = KeyCode();
		if( input_flag | key == INPUT_KEY )
		{
			if( cur == point[0] )
			{
				Warning();
				if( MESSAGE == ON )
					Message( "２点目は生成する辺を指定してください" );
			}
			else
			{
				Select( work_sel );
				SelectArea( TRUE, SELECT_AND | SELECT_SUB, cur, cur );
				if( SelectPolygons() == 0 )
				{
					Warning();
					if( MESSAGE == ON )
					{
						temp = PolyVertex( cur );
						if( temp != cur )
							Message( error_msg1 );
						else
							Message( "選択面中にこの２点で分割される面は存在しません" );
					}
					Select( sel );
				}
				else
				{
					point[1] = cur;
					break;
				}
			}
		}
		else if( key == ESC  | key == BS | quit_flag == TRUE )
		{
			PopandClear( OVERWRITE );
			Select( sel );
			return;
		}
		else
			KeyProcess( key );
		if( ((key!=0 ) & (key != INPUT_KEY)) | ( pick != Cursor()) )
		{
			draw_flag = ON;
			DrawLine( point[0], pick );
		}
		else
			draw_flag = OFF;
		pick = Cursor();
		input_flag = OFF;
	}
	Clear( OVERWRITE );
	work_sel = Select();
	EdgeSelect( Edge( point[0], point[1]), FALSE, SELECT_AND );
	if( SelectPolygons() == 0 )
	{
		PopandClear( OVERWRITE );
		if( MESSAGE == ON )
			Message( "選択面中にこの２点で分割される面は存在しません\n"
				+"最初から選択しなおしてください" );
		Select( sel );
		return;
	}
	sels = SelectPolygons();
	for( i = 0; i< sels; i++ )
	{
		PolyLoad( work_sel, i );
		vers = PolyVertexs();
		flag = OFF;
		j = 0;
		k = 0;
		while( TRUE )
		{
			temp = PolyGetVertex( j );
			if( flag == ON )
			{
				v[k] = temp;
				k++;
				if( temp == point[0] | temp == point[1] )
					break;
				else
					PolyDelVertex( j );
			}
			else
			{
				if( temp == point[0] | temp == point[1] )
				{
					flag = ON;
					v[k] = temp;
					k++;
				}
				j++;
			}
		}
		PolySave();
		for( j = 0;j<k;j++ )
			PolySetVertex( v[j], j );
		PolyVertexs( k );
		if( SelectPolygons( sel ) == 0 )
		{
			PolyAppend( FALSE );
			ViewCursor( OFF );
			DrawCurrent( FALSE );
			ViewCursor( ON );
		}
		else
		{
			PolyAppend( TRUE );
			ViewCursor( OFF );
			DrawCurrent( TRUE );
			ViewCursor( ON );
		}
	}
	Select( Select() | sel );
//	Update( OVERWRITE );
	UpdateObject();
	PopMenu();
	Status_title = Status_org;
	DrawStatus();
}

//
//	２点を指定して面を合成する
//
function JointPolygons()
{
	var	point[2];
	var	key, temp;
	var	sel, sels, work_sel;
	var	i, j;
	var	ty1, ty2, vers1, vers2, flag1, flag2, temp1, temp2;
	var	v[MAXVERTEX];
	var	pick, draw_flag = ON;

	if( SelectPolygons() == 0 )
	{
		Warning();
		if( MESSAGE == ON )
			Message( error_msg3 );
		return;
	}
	sel = Select();

	point[0] = Cursor();
	SelectArea( TRUE, SELECT_AND | SELECT_SUB, point[0], point[0] );
	work_sel = Select();
	if( SelectPolygons() < 2 )
	{
		Warning();
		if( MESSAGE == ON )
		{
			temp = PolyVertex( point[0] );
			sels = SelectPolygons();
			if( temp == point[0] )
			{
				if( sels == 0 )
					Message( "選択面中にこの点は含まれていません" );
				else if( sels == 1 )
					Message( "選択面中にこの点を含む面は１面しかありません\n"
						+"削除する辺を指定してください" );
			}
			else
				Message( error_msg1 );
		}
		Select( sel );
		return;
	}
	Select( sel );

	PushMenu();
	Status_org = Status_title;
	MenuPosition( Menu( " 動作設定(&S)",
			"合成中止	ESC",	MenuQuit
		), Menu_Title );
	ClearStatus();
	Status_title[0] = "【面合成中】";
	DrawStatus();

	quit_flag = FALSE;

	cur = Cursor();
	pick = cur;
	input_flag = OFF;
	while( TRUE )
	{
		if( draw_flag == ON )
			DrawLine( point[0], cur );
		key = WaitEvent();
		if( key )
			input_flag = ON;
		if( ( ShiftStat() & 1 ) == 1 )
		{
			cur = Cursor();
			TrimCursor(point[0], MouseWindow());
			Cursor( cur );
		}
		else
			cur = Cursor();
		key = KeyCode();
		if( input_flag | key == INPUT_KEY )
		{
			Select( work_sel );
			SelectArea( TRUE, SELECT_AND | SELECT_SUB, cur, cur );
			if( SelectPolygons() < 2 )
			{
				Warning();
				if( MESSAGE == ON )
				{
					temp = PolyVertex( cur );
					if( temp != cur )
						Message( "削除する辺を指定してください\n"
							+error_msg1 );
					else
						Message( "この辺は削除できません" );
				}
				Select( sel );
			}
			else
			{
				point[1] = cur;
				break;
			}
		}
		else if( key == ESC  | key == BS | quit_flag == TRUE )
		{
			PopandClear( OVERWRITE );
			Select( sel );
			return;
		}
		else
			temp = KeyProcess( key );
		if( ((key!=0 ) & (key != INPUT_KEY)) | ( pick != Cursor()) )
		{
			draw_flag = ON;
			DrawLine( point[0], pick );
		}
		else
			draw_flag = OFF;
		pick = Cursor();
		input_flag = OFF;
	}
	Clear( OVERWRITE );
	EdgeSelect( Edge( point[0], point[1]), TRUE, SELECT_AND );
	if( SelectPolygons() != 2 )
	{
		Warning();
		if( SelectPolygons() > 2 )
			Message( "辺を共有している面が３面以上あるので合成できません。" );
		else if( MESSAGE == ON )
		{
			Message( "この辺は隣接する面がないので削除できません" );
		}
		PopMenu();
		Status_title = Status_org;
		DrawStatus();
		Select( sel );
		return;
	}

	work_sel = Select();
	PolyLoad(work_sel, 0);
	ty1 = PolyType();
	vers1 = PolyVertexs();
	temp1 = PolyGetVertex( 0 );
	for( i = 0; i<(vers1-1);i++)
	{
		temp2 = PolyGetVertex( i+1 );
		if( temp1 == point[0] )
		{
			if( temp2 == point[1] )
			{
				flag1 = ON;
				break;
			}
		}
		else if( temp1 == point[1] )
		{
			if( temp2 == point[0] )
			{
				flag1 = OFF;
				break;
			}
		}
		temp1 = temp2;
	}
	if( i == vers1-1 )
	{
		if( temp1 == point[1] )
			flag1 = OFF;
		else
			flag1 = ON;
		PolyShiftVertex( vers1-1 );
	}
	else
		PolyShiftVertex( i );
	for( i = 0; i< vers1;i++ )
		v[i] = PolyGetVertex( i );

	PolyLoad(work_sel, 1);
	ty2 = PolyType();
	vers2 = PolyVertexs();

	temp1 = PolyGetVertex( 0 );
	if( temp1 == point[0] )
		flag2 = OFF;
	else
		flag2 = ON;
	for( i = 0; i<(vers2-1);i++ )
	{
		temp2 = PolyGetVertex( i+1 );
		if( temp1 == point[0] )
		{
			if( temp2 == point[1] )
			{
				flag2 = ON;
				break;
			}
		}
		else if( temp1 == point[1] )
		{
			if( temp2 == point[0] )
			{
				flag2 = OFF;
				break;
			}
		}
		temp1 = temp2;
	}
	if(i == (vers2-1))
	{
		if( flag1 != flag2 )
		{
			for( i = 2; i< vers1; i++ )
				PolySetVertex( v[i], vers2+i-2);
		}
		else
		{
			for( i = 2;i<vers1;i++ )
				PolySetVertex( v[vers1-i+1], vers2+i-2);
		}
		PolyVertexs( vers1+vers2-2);
	}
	else
	{
		if( flag1 != flag2 )
		{
			for( j = 2; j<vers1;j++ )
				PolyInsVertex( v[vers1-j+1], i+1 );
		}
		else
		{
			for( j = 2;j<vers1;j++ )
				PolyInsVertex( v[j], i+1 );
		}
	}
	while( TRUE )
	{
		j = PolyVertexs() -2 ;
		for( i = 0; i< j;i++)
		{
			temp1 = PolyGetVertex( i );
			temp2 = PolyGetVertex( i+2 );
			if( temp1 == temp2 )
				break;
		}
		if( i == j )
		{
			if( PolyGetVertex( 1 ) == PolyGetVertex( j+1 ) )
			{
				PolyDelVertex( 0 );
				PolyDelVertex( 0 );
			}
			else
				break;
		}
		else
		{
			PolyDelVertex( i );
			PolyDelVertex( i );
		}
	}
	PolyType( ty1 & ty2 );
	Select( sel );
	PolyAppend( TRUE );
	PolyDelete( work_sel );
	Update( CLEAR );
	UpdateObject();
	PopMenu();
	Status_title = Status_org;
	DrawStatus();
}

function MovePolygons()
{
	CopyMovePolygons( OFF );
	Update( CLEAR );
	UpdateObject();
}

function CopyPolygons()
	CopyMovePolygons( ON );

//
//	移動
//
function Move()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:平行移動】";
	DrawStatus();
	InputEvent( MovePolygons );
	KeyEvent( MovePolygons, INPUT_KEY );
}

function private RotatePolygons()
	_Rotate( OFF );

//
//	回転
//
function Rotate()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:回転】";
	DrawStatus();
	InputEvent( RotatePolygons );
	KeyEvent( RotatePolygons, INPUT_KEY );
}

function private ScalePolygons()
	_Scale( OFF );

//
//	拡大
//
function Scale()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:拡大縮小】";
	DrawStatus();
	InputEvent( ScalePolygons );
	KeyEvent( ScalePolygons, INPUT_KEY );
}

//
//	削除
//
function Delete()
{
	var	sel;

	if( SelectPolygons() != 0 )
	{
		if( MESSAGE == ON )
		{
			DlogOpen( "面削除", 1, "いいえ", " はい " );
			DlogMessage( 0,"選択されている面を削除しますがよろしいですか" );
			if( DlogWait() == 0 )
				return;
		}
		if( prevnext_flag == TRUE )
		{
			sel = Select();
			if( SelectPolygons(( sel & prevnext_sel )^sel) == 0 )
			{
				Select( prevnext_sel );
				PolyDelete( sel );
				prevnext_sel = Select();
				SelectAll( FALSE );
				if(SelectPolygons( prevnext_sel ) <= prevnext_selno )
					prevnext_selno = 0;
			}
			else
			{
				PolyDelete();
				prevnext_flag = FALSE;
			}
		}
		else
			PolyDelete();
		Update( CLEAR );
		pers_rotation_flag = FALSE;
		UpdateObject();
	}
	else
	{
		Warning();
		if( MESSAGE == ON )
			Message( "面が選択されていないので、削除できません" );
	}
}

//
//	複写
//
function Copy()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:複写】";
	DrawStatus();
	InputEvent( CopyPolygons );
	KeyEvent( CopyPolygons, INPUT_KEY );
}

//
//	グリッド複写
//
function GridCopy()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:ｸﾞﾘｯﾄﾞ複写】";
	DrawStatus();
	InputEvent( GridCopyPolygons );
	KeyEvent( GridCopyPolygons, INPUT_KEY );
}

//
//	面の方向統一
//
function UnityPoly()
{
	var	sel1, sel2, temp_sel1, temp_sel2, old_sel, new_sel;
	var	i, j, temp1, temp2, pos[2], flag;

	if( SelectPolygons() < 2 )
	{
		Warning();
		if( MESSAGE == ON )
			Message( "面の方向を揃えることができません" );
		break;
	}
	sel1 = Select();
	sel2 = sel1;
	SelectAllFalse();
	while( TRUE )
	{
		if( SelectPolygons(sel2) < 2 )
			break;
		SelectNumber( sel2, 0 );
		old_sel = Select();
		while( TRUE )
		{
			EdgeSelect( EdgeSelect(), TRUE, SELECT_UPDATE );
			new_sel = Select()&sel1;
			if( old_sel == new_sel )
				break;
			temp_sel1 = new_sel^old_sel;
			temp1 = SelectPolygons( temp_sel1 );
//print( "\nnow go ", temp1, " " );
			for( i = 0; i< temp1; i++ )
			{
				SelectNumber( temp_sel1, i );
				temp2 = EdgeSelect();
//Update( CLEAR );
//print( i ," " );
				Select( old_sel | Select());
				EdgeSelect( temp2, TRUE, SELECT_AND );
				if( SelectPolygons( Select() & temp_sel1 ) != 1 )
				{
					Warning();
					break;
				}
				temp2 = EdgeSelect() & temp2;
				temp2 = EdgeSelectCount( temp2, 2 );
				if( Edges( temp2 ) != 1 )
				{
					EdgeGetVertex(temp2, 0, pos );
					EdgeSelect(Edge(pos[0], pos[1]), TRUE, SELECT_AND );
				}
				else
				{
					EdgeGetVertex( temp2, 0, pos );
				}
//print( pos[0], pos[1], "\n" );
				temp_sel2 = Select();
				Select( temp_sel2 & old_sel );
				if( SelectPolygons() < 1 )
				{
					Warning();
					Update(CLEAR);
					break;
				}
				PolyLoad();
				flag = 0;
				for( j = 0; j< PolyVertexs(); j++ )
				{
					if( PolyGetVertex( j ) == pos[0] )
					{
						if( j == (PolyVertexs()-1))
						{
							flag = 1;
							break;
						}
						else
						{
							if( PolyGetVertex( j+1 ) == pos[1] )
							{
								flag = 1;
								break;
							}
						}
					}
					else if( PolyGetVertex( j ) == pos[1] )
					{
						if( j == (PolyVertexs() -1))
						{
							flag = 2;
							break;
						}
						else
						{
							if( PolyGetVertex( j+1 ) == pos[0] )
							{
								flag = 2;
								break;
							}
						}
					}
				}
//print( "flag=", flag, "\n" );
				Select( temp_sel2 & temp_sel1 );
				if( SelectPolygons() < 1 )
				{
					Warning();
					break;
				}
				PolyLoad();
DrawCurrent( TRUE );
				for( j = 0; j< PolyVertexs(); j++ )
				{
					if( PolyGetVertex( j ) == pos[0] )
					{
						if( j == (PolyVertexs()-1))
						{
							if( flag == 1 )
							{
								PolyInvVertex();
								PolySave();
								if( PolyType() & POLY_SHADE )
									PolyShadeInv();
							}
							break;
						}
						else
						{
							if( PolyGetVertex( j+1 ) == pos[1] )
							{
								if( flag == 1 )
								{
									PolyInvVertex();
									PolySave();
									if( PolyType() & POLY_SHADE )
										PolyShadeInv();
								}
								break;
							}
						}
					}
					else if( PolyGetVertex( j ) == pos[1] )
					{
						if( j == (PolyVertexs() -1))
						{
							if( flag == 2 )
							{
								PolyInvVertex();
								PolySave();
								if( PolyType() & POLY_SHADE )
									PolyShadeInv();
							}
							break;
						}
						else
						{
							if( PolyGetVertex( j+1 ) == pos[0] )
							{
								if( flag == 2 )
								{
									PolyInvVertex();
									PolySave();
									if( PolyType() & POLY_SHADE )
										PolyShadeInv();
								}
								break;
							}
						}
					}
				}
			}
			Select( new_sel );
			old_sel = new_sel;
		}
		sel2 = sel2^old_sel;
	}
	Select( sel1 );
	Update( CLEAR );
	UpdateObject();
}

//
//	面の方向反転（法線方向も反転）
//
function InversePoly()
{
	PolyShadeInv();
	while( PolyLoad())
	{
		PolyInvVertex();
		PolySave();
	}
	UpdatePers( CLEAR );
	UpdateObject();
}

//
//	面分割
//
function Separate()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:面分割】";
	DrawStatus();
	InputEvent( SeparatePolygons );
	KeyEvent( SeparatePolygons, INPUT_KEY );
}

//
//	面合成
//
function Joint()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:面合成】";
	DrawStatus();
	InputEvent( JointPolygons );
	KeyEvent( JointPolygons, INPUT_KEY );
}

//
//	面自動分割
//
function Calipoly()
{
	var	msg[2], i, flag;

	msg = { "凸多角形する", " 三角形にする " };

	PushMenu();
	MenuPosition( Menu( " 面自動分割中" ), Menu_Title );
	DlogOpen( "面自動分割", 1 );
	DlogSelect( 0, "分割方法", msg, 0 );
	i = DlogWait();
	if( i == TRUE )
	{
		flag = DlogAnswer( 0 );
		if( SelectPolygons() == 0 )
		{
			Warning();
			if( MESSAGE == ON )
				Message( error_msg3 );
			return;
		}
		else
		{
			ConvexConvert();
			if( flag == 1 )
				TriangleConvert();
		}
		Update( OVERWRITE );
		UpdateObject();
	}
	PopMenu();
}

//
//	面切断
//
function Zante()
{
	ClearStatus();
	Status_title[0] = "【ﾓｰﾄﾞ:面切断】";
	DrawStatus();
	InputEvent( _Zante );
	KeyEvent( _Zante, INPUT_KEY );
}

//
//	PolyIDの２つが一緒かどうか調べる
//
function private CheckPolygon( id1, id2 )
{
	var	vers1, temp, temp2, v[MAXVERTEX];
	var	i;

	PolyLoad( id1 );
	vers1 = PolyVertexs();
	temp = 0;
/*
	while( TRUE )
	{
		temp2 = PolyGetVertex( temp );
		for( i = (temp+1); i< vers1; i++ )
		{
			if( temp2 == PolyGetVertex( i ) )
				break;
		}
	}
*/
	for( i = 0; i< vers1; i++ )
		v[i] = PolyGetVertex( i );
	PolyLoad( id2 );
	if( vers1 != PolyVertexs() )
		return FALSE;
	for( i = 0; i< PolyVertexs(); i++ )
	{
		if( v[0] == PolyGetVertex( i ) )
			break;
	}
	PolyShiftVertex( i );
	if( v[1] == PolyGetVertex( 1 ))
	{
		for( i = 2; i< PolyVertexs(); i++ )
		{
			if( v[i] != PolyGetVertex( i ))
				return FALSE;
		}
		return TRUE;
	}
	else if( v[1] == PolyGetVertex( PolyVertexs() - 1 ) )
	{
		PolyInvVertex();
		PolyShiftVertex( PolyVertexs() -1 );
		for( i = 0; i< PolyVertexs(); i++ )
		{
			if( v[i] != PolyGetVertex( i ))
				return FALSE;
		}
		return TRUE;
	}
	else
		return FALSE;
}

//
//	同一面の削除
//
function DeleteSamePolygons()
{
	var	i, j, polyid, temp, temp2, sel1, sels1, sel2;
	var	hashsize;
	hashsize = atoi(Modelrc( "Stack" )) - StackPtr() - 20 - MAXVERTEX;
	if( hashsize > SelectPolygons()*6 )
		hashsize = SelectPolygons()*6;
	if( hashsize < SelectPolygons()*2 )
	{
		Message(	"処理すべき面が多すぎます。\n"+
				"選択範囲を狭めて再度実行してください。" );
		return FALSE;
	}
	else if( SelectPolygons() < 2 )
	{
		Message( "重複チェックする面を２面以上選んでください。" );
		return FALSE;
	}
	var	hash[hashsize];
//var	debug1 = 0, debug2 = 0;

	sels1 = SelectPolygons();
	for( i = 0; i< hashsize; i++ )
		hash[i] = 0;
	sel1 = Select();
	SelectAll( FALSE );
	sel2 = Select();
	Select( sel1 );
	PolyLoadInit();
	for( i = 0; i< sels1; i++ )
	{
		polyid = PolyLoad();
		temp = vector( 0,0,0);
		for( j = 0; j< PolyVertexs(); j++ )
			temp += Position( PolyGetVertex(j));
		temp2 = (0+vx(temp)*5+vy(temp)*7+vz(temp)*11) % hashsize;
		if( temp2 < 0 )
			temp2 += hashsize;
/*
if( hash[temp2] == 0 )
debug1++;
*/
		while( TRUE )
		{
			if( hash[temp2] == 0 )
			{
				hash[temp2] = polyid;
				break;
			}
			else
			{
//debug2++;
				if( CheckPolygon( hash[temp2], polyid ))
				{
					sel2 = sel2 | SelectCurrent();
					break;
				}
				else
					temp2 = ( temp2+1 ) % hashsize;
			}
		}
		PolyLoad( polyid );
	}
	PolyDelete( sel2 );
	UpdateObject();
	Update( CLEAR, WIN_PERS );
//print( debug1, "\n" );
//print( debug2 ,"\n" );
}

//
//	面の二重化
//
function DuplicatePolygon()
{
	var	sel1, i, sel1s;

	if( SelectPolygons() == 0 )
	{
		Message( "処理する面を選択してください。" );
		return FALSE;
	}
	sel1 = Select();
	sel1s = SelectPolygons();

	PolyLoadInit();
	for( i = 0; i< sel1s; i++ )
	{
		PolyLoad();
		PolyInvVertex();
		PolyAppend( TRUE );
	}
	Select( Select()^sel1 );
	PolyShadeInv();
	Update( OVERWRITE, WIN_PERS );
	UpdateObject();
}
