/* static */ void GeblGuiExtension::SampleMenuCallBack(void *appPtr,FsGuiPopUpMenu *,FsGuiPopUpMenuItem *)
{
	auto &guiExtension=*(GeblGuiExtension *)appPtr;
	auto &canvas=*guiExtension.canvasPtr;

	if(NULL!=canvas.Slhd())
	{
		YsShellExtEdit &shl=*(YsShellExtEdit *)canvas.Slhd();

		YsWString msg(L"Extension Menu Sample\n");

		YsString str;
		YsWString wStr;

		str.Printf("Number of vertices=%d\n",(int)shl.GetNumVertex());
		wStr.SetUTF8String(str);
		msg.Append(wStr);

		str.Printf("Number of polygons=%d\n",(int)shl.GetNumPolygon());
		wStr.SetUTF8String(str);
		msg.Append(wStr);

		msg.Append(L"You can write your own function in gui_extension/ysgebl_gui_extension.cpp.\n");

		canvas.MessageDialog(L"Extension Sample",msg);
	}
}
void FsGuiColorDialog::Make(FsGuiColorPalette *linkedColorPalette)
{
	this->linkedColorPalette=linkedColorPalette;

	FsGuiDialog::Initialize();

	closeBtn=AddTextButton(0,FSKEY_ESC,FSGUI_PUSHBUTTON,L"Close",YSTRUE);

	AddCustomControl(0,FSKEY_NULL,brightness,32,240,YSTRUE);

	AddCustomControl(0,FSKEY_NULL,colorBand,320,240,YSFALSE);

	AddCustomControl(0,FSKEY_NULL,curColorStatic,64,64,YSFALSE);

	hueText=AddTextBox(0,FSKEY_NULL,FsGuiTextBox::HORIZONTAL,L"H:",4,YSTRUE);
	saturationText=AddTextBox(0,FSKEY_NULL,FsGuiTextBox::HORIZONTAL,L"S:",4,YSFALSE);
	valueText=AddTextBox(0,FSKEY_NULL,FsGuiTextBox::HORIZONTAL,L"V:",4,YSFALSE);

	redText=AddTextBox(0,FSKEY_NULL,FsGuiTextBox::HORIZONTAL,L"R:",4,YSFALSE);
	greenText=AddTextBox(0,FSKEY_NULL,FsGuiTextBox::HORIZONTAL,L"G:",4,YSFALSE);
	blueText=AddTextBox(0,FSKEY_NULL,FsGuiTextBox::HORIZONTAL,L"B:",4,YSFALSE);

	AddStaticText(0,FSKEY_NULL,L"H:",YSTRUE);
	hueSlider=AddHorizontalSlider(0,FSKEY_NULL,40,0.0,1.0,YSFALSE);
	AddStaticText(0,FSKEY_NULL,L"S:",YSTRUE);
	saturationSlider=AddHorizontalSlider(0,FSKEY_NULL,40,0.0,1.0,YSFALSE);
	AddStaticText(0,FSKEY_NULL,L"V:",YSTRUE);
	valueSlider=AddHorizontalSlider(0,FSKEY_NULL,40,0.0,1.0,YSFALSE);

	AddStaticText(0,FSKEY_NULL,L"R:",YSTRUE);
	redSlider=AddHorizontalSlider(0,FSKEY_NULL,40,0.0,1.0,YSFALSE);
	AddStaticText(0,FSKEY_NULL,L"G:",YSTRUE);
	greenSlider=AddHorizontalSlider(0,FSKEY_NULL,40,0.0,1.0,YSFALSE);
	AddStaticText(0,FSKEY_NULL,L"B:",YSTRUE);
	blueSlider=AddHorizontalSlider(0,FSKEY_NULL,40,0.0,1.0,YSFALSE);

	if(NULL!=linkedColorPalette && YSTRUE==linkedColorPalette->HasColorButton())
	{
		for(int i=0; i<16; ++i)
		{
			const YSBOOL newLine=((0==i || 8==i) ? YSTRUE : YSFALSE);

			YsString str;
			str.Printf("Set C%d",i);
			setToPaletteBtn[i]=AddTextButton(0,FSKEY_NULL,FSGUI_PUSHBUTTON,str,newLine);
		}
	}
	else
	{
		for(int i=0; i<10; ++i)
		{
			setToPaletteBtn[i]=NULL;
		}
	}

	Fit();
}
YSRESULT PolyCreAboutDialog::Make(void)
{
	if(NULL==okBtn)
	{
		FsGuiDialog::Initialize();

		AddStaticText(0,FSKEY_NULL,L"Polygon Crest",YSTRUE);
		AddStaticText(0,FSKEY_NULL,L"Copyright (C) Soji Yamakawa",YSTRUE);

		YsString str;
		str.Printf("Version %d",PolygonCrestVersion);

		AddStaticText(0,FSKEY_NULL,str,YSTRUE);

		ysflightBtn=AddTextButton(0,FSKEY_NULL,FSGUI_PUSHBUTTON,L"http://www.ysflight.com",YSTRUE);

		AddStaticText(0,FSKEY_NULL,FSGUI_DLG_ABOUT_DONATELINE1,YSTRUE);
		AddStaticText(0,FSKEY_NULL,FSGUI_DLG_ABOUT_DONATELINE2,YSTRUE);

		YsLocale locale;
		const char *langStr=locale.GetLanguagePart();
		if(NULL!=langStr && 0==strncmp("ja",langStr,2))
		{
			// Japanese
			donateVectorBtn=AddTextButton(0,FSKEY_NULL,FSGUI_PUSHBUTTON,FSGUI_DLG_ABOUT_DONATEVECTOR,YSTRUE);
			AddStaticText(0,FSKEY_NULL,FSGUI_DLG_ABOUT_DONATELINE3,YSTRUE);
			donatePayPalBtn=AddTextButton(0,FSKEY_NULL,FSGUI_PUSHBUTTON,FSGUI_DLG_ABOUT_DONATEPAYPAL,YSTRUE);
		}
		else
		{
			// Non-Japanese
			donateVectorBtn=NULL;
			donatePayPalBtn=AddTextButton(0,FSKEY_NULL,FSGUI_PUSHBUTTON,FSGUI_DLG_ABOUT_DONATEPAYPAL,YSTRUE);
		}


		okBtn=AddTextButton(0,FSKEY_ENTER,FSGUI_PUSHBUTTON,FSGUI_COMMON_CLOSE,YSTRUE);

		SetArrangeType(FSDIALOG_ARRANGE_TOP_LEFT);
		SetBackgroundAlpha(1.0);
		Fit();
	}

	return YSOK;
}
void GeblGuiEditorBase::Draw(void)
{
	if(YSTRUE!=drawingMasterSwitch)
	{
		DrawGuiOnly();
		return;
	}

	// Do this at the beginning of Draw funtion.  This will allow one of the elements set SetNeedRedraw(YSTRUE) 
	// within drawing function so that Draw function will be called again in the next iteragion. >>
	SetNeedRedraw(YSFALSE);
	drawEnv.SetNeedRedraw(YSFALSE);
	threeDInterface.SetNeedRedraw(YSFALSE);
	// <<


	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(1,1);


	if(NULL==slHd)
	{
		if(NULL!=GetTopStatusBar())
		{
			GetTopStatusBar()->ClearStringAll();
		}
		if(NULL!=GetBottomStatusBar())
		{
			GetBottomStatusBar()->ClearStringAll();
		}
	}

	if(NULL!=slHd && NULL!=GetTopStatusBar())
	{
		YsWString ful,pth,fil;
		slHd->GetFileName(ful);
		ful.SeparatePathFile(pth,fil);
		if(YSTRUE==slHd->IsModified())
		{
			fil.Append(L"(*)");
		}

		YsWString curMsg;
		if(0!=YsWString::Strcmp(fil,GetTopStatusBar()->GetString(curMsg,0)))
		{
			GetTopStatusBar()->SetString(0,fil);
		}
	}

	if(NULL!=slHd && NULL!=GetBottomStatusBar())
	{
		YsString str("Selection");
		YsString append;

		{
			YsArray <YsShellVertexHandle> selVtHd;
			slHd->GetSelectedVertex(selVtHd);
			if(0<selVtHd.GetN())
			{
				append.Printf("  Vertex:%d",(int)selVtHd.GetN());
				str.Append(append);
			}
		}
		{
			YsArray <YsShellPolygonHandle> selPlHd;
			slHd->GetSelectedPolygon(selPlHd);
			if(0<selPlHd.GetN())
			{
				append.Printf("  Polygon:%d",(int)selPlHd.GetN());
				str.Append(append);
			}
		}
		{
			YsArray <YsShellExt::ConstEdgeHandle> selCeHd;
			slHd->GetSelectedConstEdge(selCeHd);
			if(0<selCeHd.GetN())
			{
				append.Printf("  ConstEdge:%d",(int)selCeHd.GetN());
				str.Append(append);
			}
		}
		{
			YsArray <YsShellExt::FaceGroupHandle> selFgHd;
			slHd->GetSelectedFaceGroup(selFgHd);
			if(0<selFgHd.GetN())
			{
				append.Printf("  FaceGroup:%d",(int)selFgHd.GetN());
				str.Append(append);
			}
		}
		GetBottomStatusBar()->SetString(0,str);
	}


	int viewport[4];
	drawEnv.GetOpenGlCompatibleViewport(viewport);
	drawEnv.SetVerticalOrientation(YSTRUE);
	drawEnv.UpdateNearFar();


	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);


	if(YsCoordSysModel==YSOPENGL)
	{
		glFrontFace(GL_CCW);
	}
	else
	{
		glFrontFace(GL_CW);
	}


	const YsMatrix4x4 &projMat=drawEnv.GetProjectionMatrix();
	const YsMatrix4x4 &viewMat=drawEnv.GetViewMatrix();
	const YsMatrix4x4 projViewMat=(projMat*viewMat);

	threeDInterface.SetViewport(viewport);
	threeDInterface.SetProjViewModelMatrix(projViewMat);


	glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);

	GLfloat glProjMat[16];
	projMat.GetOpenGlCompatibleMatrix(glProjMat);

	GLfloat glModelviewMat[16];
	viewMat.GetOpenGlCompatibleMatrix(glModelviewMat);


	// glMatrixMode(GL_PROJECTION);
	// glLoadIdentity();
	// glMultMatrixf(glProjMat);
	// glMatrixMode(GL_MODELVIEW);
	// glLoadIdentity();
	// glMultMatrixf(glModelviewMat);


	YsGLSLSetShared3DRendererProjection(glProjMat);
	YsGLSLSetShared3DRendererModelView(glModelviewMat);


	YsVec3 lightDir=YsUnitVector(YsVec3(0.1,1.0,3.0));
	const GLfloat lightDirf[]={lightDir.xf(),lightDir.yf(),lightDir.zf()};
	YsGLSLSetShared3DRendererDirectionalLightInCameraCoordinatefv(0,lightDirf);
	YsGLSLSetShared3DRendererSpecularColor(config->GetSpecularColor());
	YsGLSLSetShared3DRendererAmbientColor(config->GetAmbientColor());
	YsGLSLSetShared3DRendererLightColor(0,config->GetLightColor());



	actuallyDrawVertex=drawVertex;
	actuallyDrawConstEdge=drawConstEdge;
	actuallyDrawPolygonEdge=drawPolygonEdge;
	actuallyDrawPolygon=drawPolygon;
	actuallyDrawShrunkPolygon=drawShrunkPolygon;
	actuallyDrawNonManifoldEdge=drawNonManifoldEdge;

	if(NULL!=UIBeforeDrawCallBack)
	{
		(*UIBeforeDrawCallBack)(*this);
	}

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


	if(YSTRUE==viewDrawBackgroundGradation->GetCheck() && (NULL==guiExtension || YSTRUE!=guiExtension->DrawBackground()))
	{
// Linear interpolation looks to be too fast.  Probably need three colors.
		YsGLSLUsePlain2DRenderer(YsGLSLSharedPlain2DRenderer());
		YsGLSLUseWindowCoordinateInPlain2DDrawing(YsGLSLSharedPlain2DRenderer(),YSTRUE);

		glDepthMask(0);

		const GLfloat rect[12]=
		{
			0                   ,0,
			(GLfloat)viewport[2],0,
			0                   ,(GLfloat)viewport[3]/2.0f,
			(GLfloat)viewport[2],(GLfloat)viewport[3]/2.0f,
			0                   ,(GLfloat)viewport[3],
			(GLfloat)viewport[2],(GLfloat)viewport[3]
		};
		const GLfloat color[24]=
		{
			config->bgColor[0].Rf(),config->bgColor[0].Gf(),config->bgColor[0].Bf(),1,
			config->bgColor[0].Rf(),config->bgColor[0].Gf(),config->bgColor[0].Bf(),1,
			config->bgColor[1].Rf(),config->bgColor[1].Gf(),config->bgColor[1].Bf(),1,
			config->bgColor[1].Rf(),config->bgColor[1].Gf(),config->bgColor[1].Bf(),1,
			config->bgColor[2].Rf(),config->bgColor[2].Gf(),config->bgColor[2].Bf(),1,
			config->bgColor[2].Rf(),config->bgColor[2].Gf(),config->bgColor[2].Bf(),1
		};
		YsGLSLDrawPlain2DPrimitivefv(YsGLSLSharedPlain2DRenderer(),GL_TRIANGLE_STRIP,6,rect,color);

		glDepthMask(1);

		YsGLSLEndUsePlain2DRenderer(YsGLSLSharedPlain2DRenderer());
	}



	threeDInterface.Draw();


	if(NULL!=slHd && YSTRUE==slHd->NeedRemakeHighlightVertexBuffer())
	{
		slHd->GetHighlight().RemakeVertexBuffer(*slHd);
		slHd->SetNeedRemakeHighlightVertexBuffer(YSFALSE);
	}

	if(NEED_REMAKE_DRAWING_NONE!=needRemakeDrawingBuffer || (nullptr!=slHd && YSTRUE==slHd->GetTemporaryModification().Changed()))
	{
		RemakeDrawingBuffer(slHd,needRemakeDrawingBuffer);
		needRemakeDrawingBuffer=NEED_REMAKE_DRAWING_NONE;
		slHd->GetTemporaryModification().ClearChangeFlag();
	}
	if(NEED_REMAKE_DRAWING_NONE!=needRemakeDrawingBuffer_for_OtherShell && YSTRUE==actuallyDrawOtherShell)
	{
		YsArray <YsShellDnmContainer <YsShellExtEditGui>::Node *> allNode;
		shlGrp.GetNodePointerAll(allNode);
		for(YSSIZE_T nodeIdx=0; nodeIdx<allNode.GetN(); ++nodeIdx)
		{
			if(slHd!=allNode[nodeIdx])
			{
				RemakeDrawingBuffer(allNode[nodeIdx],needRemakeDrawingBuffer_for_OtherShell);
			}
		}
		needRemakeDrawingBuffer_for_OtherShell=NEED_REMAKE_DRAWING_NONE;
	}


	{
		GLfloat prevTfm[16];
		GLfloat curNodeTfm[16];
		if(YSTRUE==dnmEditMode)
		{
			YsMatrix4x4 curMat;
			{
				YsGLSLShaded3DRenderer renderer;
				renderer.GetModelView(prevTfm);
				curMat.CreateFromOpenGlCompatibleMatrix(prevTfm);
			}
			YsMatrix4x4 tfm=curMat*dnmState.GetNodeToRootTransformation(slHd);
			tfm.GetOpenGlCompatibleMatrix(curNodeTfm);
			YsGLSLSetShared3DRendererModelView(curNodeTfm);
		}


		YsShellExtDrawingBuffer &drawBuf=slHd->GetDrawingBuffer();
		if(YSTRUE==actuallyDrawVertex && NULL!=slHd)
		{
			GeblGuiFoundation::DrawVertex(*slHd,viewport);
		}
		if(0<drawBuf.selectedVertexPosBuffer.GetNumVertex() && NULL!=slHd)
		{
			GeblGuiFoundation::DrawSelectedVertex(*slHd,viewport);
		}
		if(0<drawBuf.selectedVertexLineBuffer.GetNumVertex() && NULL!=slHd)
		{
			GeblGuiFoundation::DrawSelectedVertexLine(*slHd);
		}
		if(YSTRUE==actuallyDrawPolygonEdge && NULL!=slHd)
		{
			GeblGuiFoundation::DrawPolygonEdge(*slHd);
		}
		if(YSTRUE==actuallyDrawShrunkPolygon && NULL!=slHd)
		{
			GeblGuiFoundation::DrawShrunkPolygon(*slHd);

		}
		if(0<drawBuf.selectedPolygonPosBuffer.GetNumVertex() && NULL!=slHd)
		{
			GeblGuiFoundation::DrawSelectedPolygon(*slHd);
		}
		if(YSTRUE==actuallyDrawConstEdge && 0<drawBuf.constEdgeVtxBuffer.GetNumVertex() && NULL!=slHd)
		{
			GeblGuiFoundation::DrawConstEdge(*slHd);
		}
		if(0<drawBuf.selectedConstEdgeVtxBuffer.GetNumVertex() && NULL!=slHd)
		{
			GeblGuiFoundation::DrawSelectedConstEdge(*slHd);
		}
		if(YSTRUE==dnmEditMode)
		{
			YsGLSLSetShared3DRendererModelView(prevTfm);
		}


		if(YSTRUE!=dnmEditMode)
		{
			DrawInGeometryEditMode();
		}
		else
		{
			DrawInDnmEditMode();
		}


		if(YSTRUE==dnmEditMode)
		{
			YsGLSLSetShared3DRendererModelView(curNodeTfm);
		}
		if(0<=drawBuf.selectedFaceGroupVtxBuffer.GetNumVertex() && NULL!=slHd)
		{
			GeblGuiFoundation::DrawSelectedFaceGroup(*slHd);
		}
		if(YSTRUE==dnmEditMode)
		{
			YsGLSLSetShared3DRendererModelView(prevTfm);
		}
	}




	if(NULL!=slHd && YSTRUE==actuallyDrawNonManifoldEdge)
	{
		if(YSTRUE==nonManifoldEdgeCache.IsModified(slHd))
		{
			nonManifoldEdgeCache.CacheNonManifoldEdge(slHd);
		}
		struct YsGLSL3DRenderer *renderer=YsGLSLSharedVariColor3DRenderer();
		YsGLSLUse3DRenderer(renderer);

		glLineWidth(3);
		YsGLSLDrawPrimitiveVtxColfv(renderer,GL_LINES,nonManifoldEdgeCache.lineVtxBuf.GetNi(),nonManifoldEdgeCache.lineVtxBuf,nonManifoldEdgeCache.lineColBuf);
		glLineWidth(1);

		YsGLSLEndUse3DRenderer(renderer);

		// The following could have easily be done by glPointSize.  However, stupid OpenGL ES 2.0 got rid of glPointSize.
		// OpenGL ES should be gone.  The hardware on the tablets and smart phones are good enough to support full-blown
		// OpenGL.  OpenGL ES will be remembered as a dark history of OpenGL.  That is bad.  Not as bad as Direct 3D though.
		renderer=YsGLSLSharedVariColorMarkerByPointSprite3DRenderer();
		YsGLSLUse3DRenderer(renderer);

#ifdef GL_PROGRAM_POINT_SIZE
		glEnable(GL_POINT_SPRITE);
		glEnable(GL_PROGRAM_POINT_SIZE);
#endif
		YsGLSLSet3DRendererUniformMarkerType(renderer,YSGLSL_MARKER_TYPE_RECT);
		YsGLSLSet3DRendererUniformMarkerDimension(renderer,3.0f);
		YsGLSLDrawPrimitiveVtxColfv(
		    renderer,GL_POINTS,
		    nonManifoldEdgeCache.pointVtxBuf.GetNi(),
		    nonManifoldEdgeCache.pointVtxBuf,
		    nonManifoldEdgeCache.pointColBuf);
#ifdef GL_PROGRAM_POINT_SIZE
		glDisable(GL_POINT_SPRITE);
		glDisable(GL_PROGRAM_POINT_SIZE);
#endif
		YsGLSLEndUse3DRenderer(renderer);
	}

	if(YSTRUE==drawHighlight)
	{
		auto &bufManager=YsGLBufferManager::GetSharedBufferManager();
		auto &highlight=slHd->GetHighlight();

		YsGLSLRenderer renderer(YsGLSLSharedFlat3DRenderer());

		const GLfloat blue[]={0.0f,0.0f,1.0f,1.0f};
		YsGLSLSet3DRendererUniformColorfv(renderer,blue);

		{
			auto unitPtr=bufManager.GetBufferUnit(highlight.highlightedEdgeVboHandle);
			if(nullptr!=unitPtr && YsGLBufferManager::Unit::EMPTY!=unitPtr->GetState())
			{
				unitPtr->GetActualBuffer()->DrawPrimitiveVtx(renderer,GL_LINES);
			}
		}

		glLineWidth(2);
		{
			auto unitPtr=bufManager.GetBufferUnit(highlight.highlightedThickEdgeVboHandle);
			if(nullptr!=unitPtr && YsGLBufferManager::Unit::EMPTY!=unitPtr->GetState())
			{
				unitPtr->GetActualBuffer()->DrawPrimitiveVtx(renderer,GL_LINES);
			}
		}
		glLineWidth(1);

		const GLfloat darkBlue[]={0.0f,0.0f,0.7f,1.0f};
		YsGLSLSet3DRendererUniformColorfv(renderer,darkBlue);
		{
			auto unitPtr=bufManager.GetBufferUnit(highlight.highlightedPolygonVboHandle);
			if(nullptr!=unitPtr && YsGLBufferManager::Unit::EMPTY!=unitPtr->GetState())
			{
				unitPtr->GetActualBuffer()->DrawPrimitiveVtx(renderer,GL_TRIANGLES);
			}
		}
	}

	if(NULL!=UIDrawCallBack3D)
	{
		UIDrawCallBack3D(*this);
	}
	if(draw3dCallBack)
	{
		draw3dCallBack();
	}


	refBmpStore->Draw();


	if(YSTRUE==drawAxis)
	{
		const GLfloat axisLength=5.0;
		GeblGuiFoundation::DrawAxis(axisLength,viewport,projMat,viewMat);
	}



	// 2D Drawing
	// glMatrixMode(GL_PROJECTION);
	// glLoadIdentity();
	// glOrtho(0.0,(double)viewport[2],(double)viewport[3],0.0,-1.0,1.0);
	// glMatrixMode(GL_MODELVIEW);
	// glLoadIdentity();

	YsGLSLUsePlain2DRenderer(YsGLSLSharedPlain2DRenderer());
	YsGLSLUseWindowCoordinateInPlain2DDrawing(YsGLSLSharedPlain2DRenderer(),YSTRUE);
	{
		if(YSTRUE==lBtnDown)
		{
			const GLfloat rect[8]=
			{
				(GLfloat)lBtnDownMx,(GLfloat)lBtnDownMy,
				(GLfloat)moveMx,    (GLfloat)lBtnDownMy,
				(GLfloat)moveMx,    (GLfloat)moveMy,
				(GLfloat)lBtnDownMx,(GLfloat)moveMy
			};
			const GLfloat color[16]=
			{
				0,0,0,0.8f,
				0,0,0,0.8f,
				0,0,0,0.8f,
				0,0,0,0.8f
			};
			YsGLSLDrawPlain2DPrimitivefv(YsGLSLSharedPlain2DRenderer(),GL_LINE_LOOP,4,rect,color);
		}
	}
	YsGLSLEndUsePlain2DRenderer(YsGLSLSharedPlain2DRenderer());

	glDisable(GL_DEPTH_TEST);

	FsGuiCanvas::Show();

	if(NULL!=UIDrawCallBack2D)
	{
		(*UIDrawCallBack2D)(*this);
	}

	FsSwapBuffers();
}