|  | @@ -0,0 +1,210 @@
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | +* Part of LaGUI demonstration programs
 | 
	
		
			
				|  |  | +* Copyright (C) 2022-2023 Wu Yiming
 | 
	
		
			
				|  |  | +*
 | 
	
		
			
				|  |  | +* This program is free software: you can redistribute it and/or modify
 | 
	
		
			
				|  |  | +* it under the terms of the GNU General Public License as published by
 | 
	
		
			
				|  |  | +* the Free Software Foundation, either version 3 of the License, or
 | 
	
		
			
				|  |  | +* (at your option) any later version.
 | 
	
		
			
				|  |  | +*
 | 
	
		
			
				|  |  | +* This program is distributed in the hope that it will be useful,
 | 
	
		
			
				|  |  | +* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
	
		
			
				|  |  | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
	
		
			
				|  |  | +* GNU General Public License for more details.
 | 
	
		
			
				|  |  | +*
 | 
	
		
			
				|  |  | +* You should have received a copy of the GNU General Public License
 | 
	
		
			
				|  |  | +* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
	
		
			
				|  |  | +*/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define NANOVG_GL3_IMPLEMENTATION
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include "la_5.h"
 | 
	
		
			
				|  |  | +extern LA MAIN;
 | 
	
		
			
				|  |  | +extern tnsMain* T;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void MyPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laShowCanvas(uil,c,0,"tns","my_nanovg_canvas",-1);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +typedef struct MyCanvas{
 | 
	
		
			
				|  |  | +    laCanvasExtra e;
 | 
	
		
			
				|  |  | +    NVGcontext* c;
 | 
	
		
			
				|  |  | +}MyCanvas;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* From NanoVG */
 | 
	
		
			
				|  |  | +void drawColorwheel(NVGcontext* vg, float x, float y, float w, float h, float t)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int i;
 | 
	
		
			
				|  |  | +	float r0, r1, ax,ay, bx,by, cx,cy, aeps, r;
 | 
	
		
			
				|  |  | +	float hue = sinf(t * 0.12f);
 | 
	
		
			
				|  |  | +	NVGpaint paint;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	nvgSave(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*	nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +	nvgRect(vg, x,y,w,h);
 | 
	
		
			
				|  |  | +	nvgFillColor(vg, nvgRGBA(255,0,0,128));
 | 
	
		
			
				|  |  | +	nvgFill(vg);*/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	cx = x + w*0.5f;
 | 
	
		
			
				|  |  | +	cy = y + h*0.5f;
 | 
	
		
			
				|  |  | +	r1 = (w < h ? w : h) * 0.5f - 5.0f;
 | 
	
		
			
				|  |  | +	r0 = r1 - 20.0f;
 | 
	
		
			
				|  |  | +	aeps = 0.5f / r1;	// half a pixel arc length in radians (2pi cancels out).
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (i = 0; i < 6; i++) {
 | 
	
		
			
				|  |  | +		float a0 = (float)i / 6.0f * NVG_PI * 2.0f - aeps;
 | 
	
		
			
				|  |  | +		float a1 = (float)(i+1.0f) / 6.0f * NVG_PI * 2.0f + aeps;
 | 
	
		
			
				|  |  | +		nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +		nvgArc(vg, cx,cy, r0, a0, a1, NVG_CW);
 | 
	
		
			
				|  |  | +		nvgArc(vg, cx,cy, r1, a1, a0, NVG_CCW);
 | 
	
		
			
				|  |  | +		nvgClosePath(vg);
 | 
	
		
			
				|  |  | +		ax = cx + cosf(a0) * (r0+r1)*0.5f;
 | 
	
		
			
				|  |  | +		ay = cy + sinf(a0) * (r0+r1)*0.5f;
 | 
	
		
			
				|  |  | +		bx = cx + cosf(a1) * (r0+r1)*0.5f;
 | 
	
		
			
				|  |  | +		by = cy + sinf(a1) * (r0+r1)*0.5f;
 | 
	
		
			
				|  |  | +		paint = nvgLinearGradient(vg, ax,ay, bx,by, nvgHSLA(a0/(NVG_PI*2),1.0f,0.55f,255), nvgHSLA(a1/(NVG_PI*2),1.0f,0.55f,255));
 | 
	
		
			
				|  |  | +		nvgFillPaint(vg, paint);
 | 
	
		
			
				|  |  | +		nvgFill(vg);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +	nvgCircle(vg, cx,cy, r0-0.5f);
 | 
	
		
			
				|  |  | +	nvgCircle(vg, cx,cy, r1+0.5f);
 | 
	
		
			
				|  |  | +	nvgStrokeColor(vg, nvgRGBA(0,0,0,64));
 | 
	
		
			
				|  |  | +	nvgStrokeWidth(vg, 1.0f);
 | 
	
		
			
				|  |  | +	nvgStroke(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// Selector
 | 
	
		
			
				|  |  | +	nvgSave(vg);
 | 
	
		
			
				|  |  | +	nvgTranslate(vg, cx,cy);
 | 
	
		
			
				|  |  | +	nvgRotate(vg, hue*NVG_PI*2);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// Marker on
 | 
	
		
			
				|  |  | +	nvgStrokeWidth(vg, 2.0f);
 | 
	
		
			
				|  |  | +	nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +	nvgRect(vg, r0-1,-3,r1-r0+2,6);
 | 
	
		
			
				|  |  | +	nvgStrokeColor(vg, nvgRGBA(255,255,255,192));
 | 
	
		
			
				|  |  | +	nvgStroke(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	paint = nvgBoxGradient(vg, r0-3,-5,r1-r0+6,10, 2,4, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0));
 | 
	
		
			
				|  |  | +	nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +	nvgRect(vg, r0-2-10,-4-10,r1-r0+4+20,8+20);
 | 
	
		
			
				|  |  | +	nvgRect(vg, r0-2,-4,r1-r0+4,8);
 | 
	
		
			
				|  |  | +	nvgPathWinding(vg, NVG_HOLE);
 | 
	
		
			
				|  |  | +	nvgFillPaint(vg, paint);
 | 
	
		
			
				|  |  | +	nvgFill(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// Center triangle
 | 
	
		
			
				|  |  | +	r = r0 - 6;
 | 
	
		
			
				|  |  | +	ax = cosf(120.0f/180.0f*NVG_PI) * r;
 | 
	
		
			
				|  |  | +	ay = sinf(120.0f/180.0f*NVG_PI) * r;
 | 
	
		
			
				|  |  | +	bx = cosf(-120.0f/180.0f*NVG_PI) * r;
 | 
	
		
			
				|  |  | +	by = sinf(-120.0f/180.0f*NVG_PI) * r;
 | 
	
		
			
				|  |  | +	nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +	nvgMoveTo(vg, r,0);
 | 
	
		
			
				|  |  | +	nvgLineTo(vg, ax,ay);
 | 
	
		
			
				|  |  | +	nvgLineTo(vg, bx,by);
 | 
	
		
			
				|  |  | +	nvgClosePath(vg);
 | 
	
		
			
				|  |  | +	paint = nvgLinearGradient(vg, r,0, ax,ay, nvgHSLA(hue,1.0f,0.5f,255), nvgRGBA(255,255,255,255));
 | 
	
		
			
				|  |  | +	nvgFillPaint(vg, paint);
 | 
	
		
			
				|  |  | +	nvgFill(vg);
 | 
	
		
			
				|  |  | +	paint = nvgLinearGradient(vg, (r+ax)*0.5f,(0+ay)*0.5f, bx,by, nvgRGBA(0,0,0,0), nvgRGBA(0,0,0,255));
 | 
	
		
			
				|  |  | +	nvgFillPaint(vg, paint);
 | 
	
		
			
				|  |  | +	nvgFill(vg);
 | 
	
		
			
				|  |  | +	nvgStrokeColor(vg, nvgRGBA(0,0,0,64));
 | 
	
		
			
				|  |  | +	nvgStroke(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// Select circle on triangle
 | 
	
		
			
				|  |  | +	ax = cosf(120.0f/180.0f*NVG_PI) * r*0.3f;
 | 
	
		
			
				|  |  | +	ay = sinf(120.0f/180.0f*NVG_PI) * r*0.4f;
 | 
	
		
			
				|  |  | +	nvgStrokeWidth(vg, 2.0f);
 | 
	
		
			
				|  |  | +	nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +	nvgCircle(vg, ax,ay,5);
 | 
	
		
			
				|  |  | +	nvgStrokeColor(vg, nvgRGBA(255,255,255,192));
 | 
	
		
			
				|  |  | +	nvgStroke(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	paint = nvgRadialGradient(vg, ax,ay, 7,9, nvgRGBA(0,0,0,64), nvgRGBA(0,0,0,0));
 | 
	
		
			
				|  |  | +	nvgBeginPath(vg);
 | 
	
		
			
				|  |  | +	nvgRect(vg, ax-20,ay-20,40,40);
 | 
	
		
			
				|  |  | +	nvgCircle(vg, ax,ay,7);
 | 
	
		
			
				|  |  | +	nvgPathWinding(vg, NVG_HOLE);
 | 
	
		
			
				|  |  | +	nvgFillPaint(vg, paint);
 | 
	
		
			
				|  |  | +	nvgFill(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	nvgRestore(vg);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	nvgRestore(vg);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void my_CanvasInit(laUiItem *ui){
 | 
	
		
			
				|  |  | +    MyCanvas* mye=memAcquire(sizeof(MyCanvas)); ui->Extra=mye;
 | 
	
		
			
				|  |  | +    la_CanvasInit(ui);
 | 
	
		
			
				|  |  | +    mye->c=nvgCreateGL3(NVG_STENCIL_STROKES|NVG_DEBUG|NVG_ANTIALIAS);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void my_CanvasDestroy(laUiItem *ui){
 | 
	
		
			
				|  |  | +    MyCanvas* mye=ui->Extra;
 | 
	
		
			
				|  |  | +    nvgDeleteGL3(mye->c);
 | 
	
		
			
				|  |  | +    la_CanvasDestroy(ui);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void my_CanvasDrawCanvas(laBoxedTheme *bt, void *unused_c, laUiItem* ui){
 | 
	
		
			
				|  |  | +    laCanvasExtra* e=ui->Extra; MyCanvas* mye=e;
 | 
	
		
			
				|  |  | +    int W, H; W = ui->R - ui->L; H = ui->B - ui->U;
 | 
	
		
			
				|  |  | +    tnsFlush();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (!e->OffScr || e->OffScr->pColor[0]->Height != ui->B - ui->U || e->OffScr->pColor[0]->Width != ui->R - ui->L){
 | 
	
		
			
				|  |  | +        if (e->OffScr) tnsDelete2DOffscreen(e->OffScr);
 | 
	
		
			
				|  |  | +        e->OffScr = tnsCreate2DOffscreen(GL_RGBA8, W, H, 0, 0, 1);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    tnsDrawToOffscreen(e->OffScr,1,0);
 | 
	
		
			
				|  |  | +    tnsViewportWithScissor(0, 0, W, H);
 | 
	
		
			
				|  |  | +    tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
 | 
	
		
			
				|  |  | +    tnsOrtho(e->PanX - W * e->ZoomX / 2, e->PanX + W * e->ZoomX / 2, e->PanY - e->ZoomY * H / 2, e->PanY + e->ZoomY * H / 2, 100, -100);
 | 
	
		
			
				|  |  | +    tnsClearColor(0,0,0,1); tnsClearAll();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    NVGcontext* vg=mye->c;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    nvgBeginFrame(vg,W,H,1);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    drawColorwheel(vg,0,0,W,H,1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    nvgEndFrame(vg);
 | 
	
		
			
				|  |  | +    tnsRestoreFromNanoVG();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void my_CanvasDrawOverlay(laUiItem* ui,int h){
 | 
	
		
			
				|  |  | +    laCanvasExtra *e = ui->Extra;
 | 
	
		
			
				|  |  | +    laBoxedTheme *bt = (*ui->Type->Theme);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    tnsUseImmShader(); tnsEnableShaderv(T->immShader);
 | 
	
		
			
				|  |  | +    tnsUniformColorMode(T->immShader,0); tnsUniformOutputColorSpace(T->immShader, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    tnsDraw2DTextureDirectly(e->OffScr->pColor[0], ui->L, ui->U, ui->R - ui->L, ui->B - ui->U);
 | 
	
		
			
				|  |  | +    tnsFlush();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    la_CanvasDefaultOverlay(ui, h);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int main(int argc, char *argv[]){
 | 
	
		
			
				|  |  | +    laGetReady();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    transSetLanguage("zh-CN");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laCanvasTemplate* ct=laRegisterCanvasTemplate("my_nanovg_canvas", 0, 0, my_CanvasDrawCanvas, my_CanvasDrawOverlay, my_CanvasInit, my_CanvasDestroy);
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | +    laRegisterUiTemplate("nanovg_panel","NanoVG Panel", MyPanel,0,0,"NanoVG Demonstration", 0,0,0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laWindow* w = laDesignWindow(-1,-1,600,600);
 | 
	
		
			
				|  |  | +    laLayout* l = laDesignLayout(w,"My Layout");
 | 
	
		
			
				|  |  | +    laCreatePanel(l->FirstBlock,"nanovg_panel");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laStartWindow(w);
 | 
	
		
			
				|  |  | +    laMainLoop();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 |