/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/**
 * @file GridCursor.cpp
 * @brief GridCursor.h ‚ÌŽÀ‘•
 */
#include "stdafx.h"
#include "mgGL/OpenGLView.h"
#include "mgGL/Texture.h"
#include "mgGL/VBOLeaf.h"
#include "Common/LocateInfo.h"
#include "Common/GridCursor.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

namespace{GLenum glErr;};

void MGGridCursor::make_display_list(
	MGCL::VIEWMODE viewMode
){
	clearElements();
	draw_contents();//	setDirty(false) is invoked in draw_contents().
}

//Draw the grid cursor.
void MGGridCursor::draw(MGCL::VIEWMODE viewMode){
	if(!m_cursor)
		return;
	if(m_cursor->sdim()<2)
		return;

// 1. Draw input lines except for the cursor.
	make_display_list();//make for non cursor data.
	mgVBO::draw();//Draw except for the cursor.

// 2. Cursor drawing.
	mgVBO* cursorImage=getGridCursor();
	mgVBOLeaf* leaf=static_cast<mgVBOLeaf*>(cursorImage->back().get());
	leaf->updateVertex(0,*m_cursor);

	GLboolean depthEnabled=glIsEnabled(GL_DEPTH_TEST);
	glDisable(GL_DEPTH_TEST);

	GLboolean blendEnabled=glIsEnabled(GL_BLEND);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_POINT_SPRITE);

	cursorImage->draw();

	if(!blendEnabled)//Restore blendEnabled.
		glDisable(GL_BLEND);
	if(depthEnabled)//Restore depthEnabled.
		glEnable(GL_DEPTH_TEST);
	glDisable(GL_POINT_SPRITE);
}

//Singleton cursor get.
mgVBO* MGGridCursor::getGridCursor(){
	static mgVBO gridCursor;
	if(gridCursor.elementNumber()==0){
		//Initialize gridCursor.
		gridCursor.Begin(GL_POINTS);
			gridCursor.setStaticAttribPointSize(float(m_gridCursorTexture->width()));
			gridCursor.Vertex(*m_cursor);
			gridCursor.setDrawType(mgGLSL::gridTexture);
			gridCursor.setTexture(m_gridCursorTexture);
		gridCursor.End();
		gridCursor.setDirty(false);
	}
	return &gridCursor;
}

///Points drawer service program.
 void MGGridCursor::draw_points(){
	const auto& ipos=*m_lpoints;
	if(ipos.size()<=0)
		return;
	double size=mgVBOElement::getDefaultPointSize();
	LInfoVec::const_iterator i,ibegin=ipos.begin(), iend=ipos.end();
	Begin(GL_POINTS);
		setStaticAttribColor(m_pointColor);
		setStaticAttribPointSize((float)size);//
		for(i=ibegin; i!=iend; i++)
			Vertex((*i)->point_world());
	End();

	Begin(GL_POINTS);
		setStaticAttribColor(MGColor::get_instance(MGColor::White));
		setStaticAttribPointSize((float)size-2.f);//
		for(i=ibegin; i!=iend; i++)
			Vertex((*i)->point_world());
	End();
}
	
///Polyline drawer service program.
void MGGridCursor::draw_lines(){
	const auto& ipos=*m_lpoints;
	size_t n = ipos.size();
	if(n<=0)
		return;

	int kind=GL_LINE_STRIP;
	Begin(kind);
	setStaticAttribColor(m_lineColor);//line color
	if(m_LWidthPLine>0.)
		setStaticAttribLineWidth(m_LWidthPLine);//line width
	for(size_t i = 0; i < n; i++){
		const MGPosition& Pi=ipos[i]->point_world();
		Vertex3d(Pi[0],Pi[1],Pi[2]);
	}
	End();
}

void MGGridCursor::draw_contents(){
	switch(m_pointDrawKind){

	case(POINTLINE_IPDRAW):
	case(POINT_IPDRAW):
		draw_points();
		if(m_pointDrawKind==POINT_IPDRAW)
			break;
	case(LINE_IPDRAW):
		if(m_lpoints->size()>=2){
			draw_lines();
		}
		if(m_pointDrawKind==LINE_IPDRAW)
			break;
	case(NO_IPDRAW):
		break;
	default:;

	}

	//Draw rubberband line.
	size_t n=m_lpoints->size();
	if(m_rubberKind==LINE_RUBBER && n){
		const MGPosition& lastP=m_lpoints->back()->point_world();
		m_lineToCursorColor.exec(*this);
		if(m_LWidthRubber>0.)
			setStaticAttribLineWidth(m_LWidthRubber);//line width
		drawStraight(lastP,cursor());
	}

	setDirty(false);
}
