void drawSearchBox(struct NVGcontext* vg, const char* text, float x, float y, float w, float h) { struct NVGpaint bg; char icon[8]; float cornerRadius = h/2-1; // Edit bg = nvgBoxGradient(vg, x,y+1.5f, w,h, h/2,5, nvgRGBA(0,0,0,16), nvgRGBA(0,0,0,92)); nvgBeginPath(vg); nvgRoundedRect(vg, x,y, w,h, cornerRadius); nvgFillPaint(vg, bg); nvgFill(vg); /* nvgBeginPath(vg); nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f); nvgStrokeColor(vg, nvgRGBA(0,0,0,48)); nvgStroke(vg);*/ nvgFontSize(vg, h*1.3f); nvgFontFace(vg, "icons"); nvgFillColor(vg, nvgRGBA(255,255,255,64)); nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); nvgText(vg, x+h*0.55f, y+h*0.55f, cpToUTF8(ICON_SEARCH,icon), NULL); nvgFontSize(vg, 20.0f); nvgFontFace(vg, "sans"); nvgFillColor(vg, nvgRGBA(255,255,255,32)); nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); nvgText(vg, x+h*1.05f,y+h*0.5f,text, NULL); nvgFontSize(vg, h*1.3f); nvgFontFace(vg, "icons"); nvgFillColor(vg, nvgRGBA(255,255,255,32)); nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); nvgText(vg, x+w-h*0.55f, y+h*0.55f, cpToUTF8(ICON_CIRCLED_CROSS,icon), NULL); }
JNIEXPORT void JNICALL Java_firststep_internal_NVG_fill (JNIEnv *e, jclass c, jlong ctx) { nvgFill((NVGcontext*)ctx); }
void drawUI(NVGcontext *vg, int item, int corners) { const UIData *head = (const UIData *)uiGetHandle(item); UIrect rect = uiGetRect(item); if (uiGetState(item) == UI_FROZEN) { nvgGlobalAlpha(vg, BND_DISABLED_ALPHA); } if (head) { switch(head->subtype) { default: { testrect(vg,rect); drawUIItems(vg,item,corners); } break; case ST_HBOX: { drawUIItemsHbox(vg, item); } break; case ST_VBOX: { drawUIItemsVbox(vg, item); } break; case ST_PANEL: { bndBevel(vg,rect.x,rect.y,rect.w,rect.h); drawUIItems(vg,item,corners); } break; case ST_LABEL: { assert(head); const UIButtonData *data = (UIButtonData*)head; bndLabel(vg,rect.x,rect.y,rect.w,rect.h, data->iconid,data->label); } break; case ST_BUTTON: { const UIButtonData *data = (UIButtonData*)head; bndToolButton(vg,rect.x,rect.y,rect.w,rect.h, corners,(BNDwidgetState)uiGetState(item), data->iconid,data->label); } break; case ST_CHECK: { const UICheckData *data = (UICheckData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); if (*data->option) state = BND_ACTIVE; bndOptionButton(vg,rect.x,rect.y,rect.w,rect.h, state, data->label); } break; case ST_RADIO:{ const UIRadioData *data = (UIRadioData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); if (*data->value == item) state = BND_ACTIVE; bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h, corners,state, data->iconid,data->label); } break; case ST_SLIDER:{ const UISliderData *data = (UISliderData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); static char value[32]; sprintf(value,"%.0f%%",(*data->progress)*100.0f); bndSlider(vg,rect.x,rect.y,rect.w,rect.h, corners,state, *data->progress,data->label,value); } break; case ST_TEXT: { const UITextData *data = (UITextData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); int idx = strlen(data->text); bndTextField(vg,rect.x,rect.y,rect.w,rect.h, corners,state, -1, data->text, idx, idx); } break; case ST_DEMOSTUFF: { draw_demostuff(vg, rect.x, rect.y, rect.w, rect.h); } break; case ST_RECT: { const UIRectData *data = (UIRectData*)head; if (rect.w && rect.h) { BNDwidgetState state = (BNDwidgetState)uiGetState(item); nvgSave(vg); nvgStrokeColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.9f)); if (state != BND_DEFAULT) { nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.5f)); } else { nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.1f)); } nvgStrokeWidth(vg,2); nvgBeginPath(vg); #if 0 nvgRect(vg,rect.x,rect.y,rect.w,rect.h); #else nvgRoundedRect(vg,rect.x,rect.y,rect.w,rect.h,3); #endif nvgFill(vg); nvgStroke(vg); if (state != BND_DEFAULT) { nvgFillColor(vg, nvgRGBAf(0.0f,0.0f,0.0f,1.0f)); nvgFontSize(vg, 15.0f); nvgBeginPath(vg); nvgTextAlign(vg, NVG_ALIGN_TOP|NVG_ALIGN_CENTER); nvgTextBox(vg, rect.x, rect.y+rect.h*0.3f, rect.w, data->label, NULL); } nvgRestore(vg); } nvgSave(vg); nvgIntersectScissor(vg, rect.x, rect.y, rect.w, rect.h); drawUIItems(vg,item,corners); nvgRestore(vg); } break; } } else { testrect(vg,rect); drawUIItems(vg,item,corners); } if (uiGetState(item) == UI_FROZEN) { nvgGlobalAlpha(vg, 1.0); } }
void NVGRenderer::fill() { nvgFill(m_context); }
void ColorWheel::draw(NVGcontext *ctx) { Widget::draw(ctx); if (!mVisible) return; float x = mPos.x(), y = mPos.y(), w = mSize.x(), h = mSize.y(); NVGcontext* vg = ctx; int i; float r0, r1, ax,ay, bx,by, cx,cy, aeps, r; float hue = mHue; NVGpaint paint; nvgSave(vg); cx = x + w*0.5f; cy = y + h*0.5f; r1 = (w < h ? w : h) * 0.5f - 5.0f; r0 = r1 * .75f; 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 float u = std::max(r1/50, 1.5f); u = std::min(u, 4.f); nvgStrokeWidth(vg, u); nvgBeginPath(vg); nvgRect(vg, r0-1,-2*u,r1-r0+2,4*u); 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 float sx = r*(1 - mWhite - mBlack) + ax*mWhite + bx*mBlack; float sy = ay*mWhite + by*mBlack; nvgStrokeWidth(vg, u); nvgBeginPath(vg); nvgCircle(vg, sx,sy,2*u); nvgStrokeColor(vg, nvgRGBA(255,255,255,192)); nvgStroke(vg); nvgRestore(vg); nvgRestore(vg); }
void Button::draw(NVGcontext *ctx) { Widget::draw(ctx); NVGcolor gradTop = mTheme->mButtonGradientTopUnfocused; NVGcolor gradBot = mTheme->mButtonGradientBotUnfocused; if (mPushed) { gradTop = mTheme->mButtonGradientTopPushed; gradBot = mTheme->mButtonGradientBotPushed; } else if (mMouseFocus && mEnabled) { gradTop = mTheme->mButtonGradientTopFocused; gradBot = mTheme->mButtonGradientBotFocused; } nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 1, mPos.y() + 1.0f, mSize.x() - 2, mSize.y() - 2, mTheme->mButtonCornerRadius - 1); if(mBackgroundColor.w() != 0) { nvgFillColor(ctx, mBackgroundColor); nvgFill(ctx); if(mPushed) { gradTop.a = gradBot.a = 0.8f; } else { double v = 1-mBackgroundColor.w(); gradTop.a = gradBot.a = mEnabled ? v : 0.5f; gradTop.a = gradBot.a = (mMouseFocus && mEnabled) ? gradTop.a+0.2 : gradTop.a; } } NVGpaint bg = nvgLinearGradient(ctx, mPos.x(), mPos.y(), mPos.x(), mPos.y() + mSize.y(), gradTop, gradBot); nvgFillPaint(ctx, bg); nvgFill(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 0.5f, mPos.y() + (mPushed ? 0.5f : 1.5f), mSize.x() - 1, mSize.y() - 1 - (mPushed ? 0.0f : 1.0f), mTheme->mButtonCornerRadius); nvgStrokeColor(ctx, mTheme->mBorderLight); nvgStroke(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 0.5f, mPos.y() + 0.5f, mSize.x() - 1, mSize.y() - 2, mTheme->mButtonCornerRadius); nvgStrokeColor(ctx, mTheme->mBorderDark); nvgStroke(ctx); nvgFontSize(ctx, mFontSize == -1 ? mTheme->mButtonFontSize : mFontSize); nvgFontFace(ctx, "sans-bold"); float tw = nvgTextBounds(ctx, 0,0, mCaption.c_str(), nullptr, nullptr); Vector2f center = mPos.cast<float>() + mSize.cast<float>() * 0.5f; Vector2f textPos(center.x() - tw * 0.5f, center.y() - 1); NVGcolor textColor = mTextColor.w() == 0 ? mTheme->mTextColor : mTextColor; if (!mEnabled) textColor = mTheme->mDisabledTextColor; if (mIcon) { auto icon = utf8(mIcon); float iw, ih = mFontSize == -1 ? mTheme->mButtonFontSize : mFontSize; if (nvgIsFontIcon(mIcon)) { ih *= 1.5f; nvgFontSize(ctx, ih); nvgFontFace(ctx, "icons"); iw = nvgTextBounds(ctx, 0, 0, icon.data(), nullptr, nullptr); } else { int w, h; ih *= 0.9f; nvgImageSize(ctx, mIcon, &w, &h); iw = w * ih / h; } if (mCaption != "") iw += mSize.y() * 0.15f; nvgFillColor(ctx, textColor); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); Vector2f iconPos = center; iconPos.y() -= 1; if (mIconPosition == LeftCentered) { iconPos.x() -= (tw + iw) * 0.5f; textPos.x() += iw * 0.5f; } else if (mIconPosition == RightCentered) { textPos.x() -= iw * 0.5f; iconPos.x() += tw * 0.5f; } else if (mIconPosition == Left) { iconPos.x() = mPos.x() + 8; } else if (mIconPosition == Right) { iconPos.x() = mPos.x() + mSize.x() - iw - 8; } if (nvgIsFontIcon(mIcon)) { nvgText(ctx, iconPos.x(), iconPos.y()+1, icon.data(), nullptr); } else { NVGpaint imgPaint = nvgImagePattern(ctx, iconPos.x(), iconPos.y() - ih/2, iw, ih, 0, mIcon, mEnabled ? 0.5f : 0.25f); nvgFillPaint(ctx, imgPaint); nvgFill(ctx); } } nvgFontSize(ctx, mFontSize == -1 ? mTheme->mButtonFontSize : mFontSize); nvgFontFace(ctx, "sans-bold"); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); nvgFillColor(ctx, mTheme->mTextColorShadow); nvgText(ctx, textPos.x(), textPos.y(), mCaption.c_str(), nullptr); nvgFillColor(ctx, textColor); nvgText(ctx, textPos.x(), textPos.y()+1, mCaption.c_str(), nullptr); }
int main() { GLFWwindow* window; NVGcontext* vg = NULL; GPUtimer gpuTimer; PerfGraph fps, cpuGraph, gpuGraph; double prevt = 0, cpuTime = 0; NVGLUframebuffer* fb = NULL; int winWidth, winHeight; int fbWidth, fbHeight; float pxRatio; if (!glfwInit()) { printf("Failed to init GLFW."); return -1; } initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time"); initGraph(&cpuGraph, GRAPH_RENDER_MS, "CPU Time"); initGraph(&gpuGraph, GRAPH_RENDER_MS, "GPU Time"); glfwSetErrorCallback(errorcb); #ifndef _WIN32 // don't require this on win32, and works with more cards glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #endif glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1); #ifdef DEMO_MSAA glfwWindowHint(GLFW_SAMPLES, 4); #endif window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL); // window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL); if (!window) { glfwTerminate(); return -1; } glfwSetKeyCallback(window, key); glfwMakeContextCurrent(window); #ifdef NANOVG_GLEW glewExperimental = GL_TRUE; if(glewInit() != GLEW_OK) { printf("Could not init glew.\n"); return -1; } // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. glGetError(); #endif #ifdef DEMO_MSAA vg = nvgCreateGL3(NVG_STENCIL_STROKES | NVG_DEBUG); #else vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG); #endif if (vg == NULL) { printf("Could not init nanovg.\n"); return -1; } // Create hi-dpi FBO for hi-dpi screens. glfwGetWindowSize(window, &winWidth, &winHeight); glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Calculate pixel ration for hi-dpi devices. pxRatio = (float)fbWidth / (float)winWidth; // The image pattern is tiled, set repeat on x and y. fb = nvgluCreateFramebuffer(vg, (int)(100*pxRatio), (int)(100*pxRatio), NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); if (fb == NULL) { printf("Could not create FBO.\n"); return -1; } if (loadFonts(vg) == -1) { printf("Could not load fonts\n"); return -1; } glfwSwapInterval(0); initGPUTimer(&gpuTimer); glfwSetTime(0); prevt = glfwGetTime(); while (!glfwWindowShouldClose(window)) { double mx, my, t, dt; float gpuTimes[3]; int i, n; t = glfwGetTime(); dt = t - prevt; prevt = t; startGPUTimer(&gpuTimer); glfwGetCursorPos(window, &mx, &my); glfwGetWindowSize(window, &winWidth, &winHeight); glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Calculate pixel ration for hi-dpi devices. pxRatio = (float)fbWidth / (float)winWidth; renderPattern(vg, fb, t, pxRatio); // Update and render glViewport(0, 0, fbWidth, fbHeight); glClearColor(0.3f, 0.3f, 0.32f, 1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); nvgBeginFrame(vg, winWidth, winHeight, pxRatio); // Use the FBO as image pattern. if (fb != NULL) { NVGpaint img = nvgImagePattern(vg, 0, 0, 100, 100, 0, fb->image, 1.0f); nvgSave(vg); for (i = 0; i < 20; i++) { nvgBeginPath(vg); nvgRect(vg, 10 + i*30,10, 10, winHeight-20); nvgFillColor(vg, nvgHSLA(i/19.0f, 0.5f, 0.5f, 255)); nvgFill(vg); } nvgBeginPath(vg); nvgRoundedRect(vg, 140 + sinf(t*1.3f)*100, 140 + cosf(t*1.71244f)*100, 250, 250, 20); nvgFillPaint(vg, img); nvgFill(vg); nvgStrokeColor(vg, nvgRGBA(220,160,0,255)); nvgStrokeWidth(vg, 3.0f); nvgStroke(vg); nvgRestore(vg); } renderGraph(vg, 5,5, &fps); renderGraph(vg, 5+200+5,5, &cpuGraph); if (gpuTimer.supported) renderGraph(vg, 5+200+5+200+5,5, &gpuGraph); nvgEndFrame(vg); // Measure the CPU time taken excluding swap buffers (as the swap may wait for GPU) cpuTime = glfwGetTime() - t; updateGraph(&fps, dt); updateGraph(&cpuGraph, cpuTime); // We may get multiple results. n = stopGPUTimer(&gpuTimer, gpuTimes, 3); for (i = 0; i < n; i++) updateGraph(&gpuGraph, gpuTimes[i]); glfwSwapBuffers(window); glfwPollEvents(); } nvgluDeleteFramebuffer(fb); nvgDeleteGL3(vg); printf("Average Frame Time: %.2f ms\n", getGraphAverage(&fps) * 1000.0f); printf(" CPU Time: %.2f ms\n", getGraphAverage(&cpuGraph) * 1000.0f); printf(" GPU Time: %.2f ms\n", getGraphAverage(&gpuGraph) * 1000.0f); glfwTerminate(); return 0; }
void drawColorwheel(struct 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); struct 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 Application::drawDebugUI() { NVGcontext* nvg = context->nvgContext; nvgBeginFrame(nvg, context->getScreenWidth(), context->getScreenHeight(),1.0f); nvgResetScissor(nvg); rootRegion.drawDebug(context.get()); Region* onTop = context->getOnTopRegion(); if (onTop != nullptr) { onTop->drawDebug(context.get()); } float cr = context->theme.CORNER_RADIUS; if (context->getViewport().contains(context->cursorPosition)) { nvgFontSize(nvg, 15); nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); /* int alignment = 0; if (context->cursorPosition.x < context->width() * 0.5f) { alignment = NVG_ALIGN_LEFT; } else { alignment = NVG_ALIGN_RIGHT; } if (context->cursorPosition.y < context->height() * 0.5f) { alignment |= NVG_ALIGN_TOP; } else { alignment |= NVG_ALIGN_BOTTOM; } std::string txt = MakeString() << std::setprecision(4) << " " << context->cursorPosition; nvgTextAlign(nvg, alignment); nvgFillColor(nvg, Color(0, 0, 0, 128)); if (context->hasFocus) { drawText(nvg, context->cursorPosition, txt, FontStyle::Outline, Color(255), Color(64, 64, 64)); } */ nvgTextAlign(nvg, NVG_ALIGN_TOP); float yoffset = 5; std::string txt = context->hasFocus ? "Window Has Focus" : "Window Lost Focus"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; if (context->mouseOverRegion != nullptr) { txt = MakeString() << "Mouse Over [" << context->mouseOverRegion->name << "] " << context->cursorPosition; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->mouseDownRegion != nullptr) { txt = MakeString() << "Mouse Down [" << context->mouseDownRegion->name << "] " << context->cursorDownPosition; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->mouseFocusRegion != nullptr) { txt = MakeString() << "Mouse Focus [" << context->mouseFocusRegion->name << "]"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->onTopRegion != nullptr) { txt = MakeString() << "On Top [" << context->onTopRegion->name << ": " << (context->onTopRegion->isVisible() ? "Visible" : "Hidden") << "]"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->leftMouseButton) { txt = "Left Mouse Button Down"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->rightMouseButton) { txt = "Right Mouse Button Down"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->hasFocus) { nvgBeginPath(nvg); nvgLineCap(nvg, NVG_ROUND); nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, Color(255, 255, 255, 255)); nvgMoveTo(nvg, context->cursorPosition.x - cr, context->cursorPosition.y); nvgLineTo(nvg, context->cursorPosition.x + cr, context->cursorPosition.y); nvgMoveTo(nvg, context->cursorPosition.x, context->cursorPosition.y - cr); nvgLineTo(nvg, context->cursorPosition.x, context->cursorPosition.y + cr); nvgStroke(nvg); nvgBeginPath(nvg); nvgFillColor(nvg, Color(255, 255, 255, 255)); nvgCircle(nvg, context->cursorPosition.x, context->cursorPosition.y, 3.0f); nvgFill(nvg); nvgBeginPath(nvg); nvgFillColor(nvg, Color(255, 64, 32, 255)); nvgCircle(nvg, context->cursorPosition.x, context->cursorPosition.y, 1.5f); nvgFill(nvg); } } nvgEndFrame(nvg); }
void nvguRect(NVGcontext* ctx, float x, float y, float w, float h) { nvgBeginPath(ctx); nvgRect(ctx, x, y, w, h); nvgFill(ctx); }
void Screen::drawWidgets() { if (!mVisible) return; Vector2i oldFBSize(mFBSize); glfwMakeContextCurrent(mGLFWWindow); glfwGetFramebufferSize(mGLFWWindow, &mFBSize[0], &mFBSize[1]); glfwGetWindowSize(mGLFWWindow, &mSize[0], &mSize[1]); glViewport(0, 0, mFBSize[0], mFBSize[1]); if (oldFBSize != mFBSize) framebufferSizeChanged(); /* Calculate pixel ratio for hi-dpi devices. */ mPixelRatio = (float) mFBSize[0] / (float) mSize[0]; nvgBeginFrame(mNVGContext, mSize[0], mSize[1], mPixelRatio); nvgTranslate(mNVGContext, -2, -2); draw(mNVGContext); double elapsed = glfwGetTime() - mLastInteraction; if (elapsed > 0.5f) { /* Draw tooltips */ const Widget *widget = findWidget(mMousePos); if (widget && !widget->tooltip().empty()) { int tooltipWidth = 150; float bounds[4]; nvgFontFace(mNVGContext, "sans"); nvgFontSize(mNVGContext, 15.0f); nvgTextAlign(mNVGContext, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); nvgTextLineHeight(mNVGContext, 1.1f); Vector2i pos = widget->absolutePosition() + Vector2i(widget->width() / 2, widget->height() + 10); nvgTextBoxBounds(mNVGContext, pos.x(), pos.y(), tooltipWidth, widget->tooltip().c_str(), nullptr, bounds); nvgGlobalAlpha(mNVGContext, std::min(1.0, 2 * (elapsed - 0.5f)) * 0.8); nvgBeginPath(mNVGContext); nvgFillColor(mNVGContext, Color(0, 255)); int h = (bounds[2] - bounds[0]) / 2; nvgRoundedRect(mNVGContext, bounds[0] - 4 - h, bounds[1] - 4, (int) (bounds[2] - bounds[0]) + 8, (int) (bounds[3] - bounds[1]) + 8, 3); int px = (int) ((bounds[2] + bounds[0]) / 2) - h; nvgMoveTo(mNVGContext, px, bounds[1] - 10); nvgLineTo(mNVGContext, px + 7, bounds[1] + 1); nvgLineTo(mNVGContext, px - 7, bounds[1] + 1); nvgFill(mNVGContext); nvgFillColor(mNVGContext, Color(255, 255)); nvgFontBlur(mNVGContext, 0.0f); nvgTextBox(mNVGContext, pos.x() - h, pos.y(), tooltipWidth, widget->tooltip().c_str(), nullptr); } } nvgEndFrame(mNVGContext); }
void drawClock(NVGcontext* vg, int screenWidth, int screenHeight) { int clockRadius = (fmin(screenWidth, screenHeight) - 10) / 2; NVGcolor baseColor = nvgRGB(145, 100, 0); NVGcolor lighterColor = nvgRGB(200, 140, 0); NVGcolor dblLighterColor = nvgRGB(255, 177, 0); NVGcolor lightestColor = nvgRGB(255, 195, 60); int widthLight = fmax(clockRadius * 0.0075, 1); int widthMedium = fmax(clockRadius * 0.013, 1); int widthHeavy = fmax(clockRadius * 0.025, 1); time_t t = time(NULL); struct tm localTime = *localtime(&t); nvgTranslate(vg, screenWidth / 2, screenHeight / 2); nvgStrokeColor(vg, baseColor); // Frame nvgSave(vg); nvgBeginPath(vg); nvgCircle(vg, 0, 0, clockRadius); nvgStrokeWidth(vg, widthMedium); nvgStroke(vg); nvgBeginPath(vg); nvgStrokeColor(vg, lighterColor); for (int i = 0; i < 12; i++) { nvgMoveTo(vg, 0, -clockRadius * 0.98); nvgLineTo(vg, 0, -clockRadius * 0.90); for (int j = 0; j < 5; j++) { nvgRotate(vg, 2 * M_PI / 12 / 5); nvgMoveTo(vg, 0, -clockRadius * 0.98); nvgLineTo(vg, 0, -clockRadius * 0.95); } } nvgStroke(vg); nvgBeginPath(vg); nvgFontFace(vg, "bold"); int digitsRadius = clockRadius * 0.79; int digitLargeSize = clockRadius * 0.29; int digitSmallSize = clockRadius * 0.2; int clockTitleSize = clockRadius * 0.06; nvgFillColor(vg, dblLighterColor); char* nineTitle = "9"; nvgFontSize(vg, digitLargeSize); nvgTranslate(vg, -digitsRadius, 0); nvgRotate(vg, - 3 * 2 * M_PI / 12); //nvgTranslate(vg, 0, -digitsRadius); drawTextCenter(vg, nineTitle, 0, 0); nvgFill(vg); nvgFillColor(vg, lighterColor); char* tenTitle = "10"; nvgFontSize(vg, digitSmallSize); nvgTranslate(vg, 0, digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, -digitsRadius); drawTextCenter(vg, tenTitle, 0, 0); nvgFill(vg); char* elevenTitle = "11"; nvgTranslate(vg, 0, digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, -digitsRadius); drawTextCenter(vg, elevenTitle, 0, 0); nvgFill(vg); nvgFillColor(vg, dblLighterColor); char* twelveTitle = "12"; nvgFontSize(vg, digitLargeSize); nvgTranslate(vg, 0, digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, -digitsRadius); drawTextCenter(vg, twelveTitle, 0, 0); nvgFill(vg); nvgFillColor(vg, lighterColor); char* oneTitle = "1"; nvgFontSize(vg, digitSmallSize); nvgTranslate(vg, 0, digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, -digitsRadius); drawTextCenter(vg, oneTitle, 0, 0); nvgFill(vg); char* twoTitle = "2"; nvgTranslate(vg, 0, digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, -digitsRadius); drawTextCenter(vg, twoTitle, 0, 0); nvgFill(vg); nvgFillColor(vg, dblLighterColor); char* threeTitle = "3"; nvgFontSize(vg, digitLargeSize); nvgTranslate(vg, 0, digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, -digitsRadius); drawTextCenter(vg, threeTitle, 0, 0); nvgFill(vg); nvgFillColor(vg, lighterColor); char* fourTitle = "4"; nvgFontSize(vg, digitSmallSize); nvgTranslate(vg, 0, digitsRadius); nvgRotate(vg, 2 * M_PI / 12 - M_PI); nvgTranslate(vg, 0, digitsRadius); drawTextCenter(vg, fourTitle, 0, 0); nvgFill(vg); char* fiveTitle = "5"; nvgTranslate(vg, 0, -digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, digitsRadius); drawTextCenter(vg, fiveTitle, 0, 0); nvgFill(vg); nvgFillColor(vg, dblLighterColor); char* sixTitle = "6"; nvgFontSize(vg, digitLargeSize); nvgTranslate(vg, 0, -digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, digitsRadius); drawTextCenter(vg, sixTitle, 0, 0); nvgFill(vg); nvgFillColor(vg, lighterColor); char* sevenTitle = "7"; nvgFontSize(vg, digitSmallSize); nvgTranslate(vg, 0, -digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, digitsRadius); drawTextCenter(vg, sevenTitle, 0, 0); nvgFill(vg); char* eightTitle = "8"; nvgTranslate(vg, 0, -digitsRadius); nvgRotate(vg, 2 * M_PI / 12); nvgTranslate(vg, 0, digitsRadius); drawTextCenter(vg, eightTitle, 0, 0); nvgFill(vg); nvgRestore(vg); nvgSave(vg); nvgFontFace(vg, "black"); char* clockTitle = "ALPHA"; nvgFontSize(vg, clockTitleSize); nvgFillColor(vg, baseColor); nvgTranslate(vg, 0, clockTitleSize); nvgTextLetterSpacing(vg, clockTitleSize); drawTextCenter(vg, clockTitle, 0, -2 * clockTitleSize); nvgFill(vg); nvgRestore(vg); double secAngle = 2 * M_PI / 60 * localTime.tm_sec; double minAngle = 2 * M_PI / 60 * localTime.tm_min + secAngle / 60; double hrAngle = 2 * M_PI / 12 * localTime.tm_hour + minAngle / 60; // Hour hand nvgStrokeColor(vg, lighterColor); nvgSave(vg); nvgRotate(vg, hrAngle); nvgBeginPath(vg); nvgMoveTo(vg, 0, clockRadius * 0.02); nvgLineTo(vg, 0, -clockRadius * 0.5); nvgStrokeWidth(vg, widthHeavy); nvgStroke(vg); nvgRestore(vg); // Minute hand nvgStrokeColor(vg, lighterColor); nvgSave(vg); nvgRotate(vg, minAngle); nvgBeginPath(vg); nvgMoveTo(vg, 0, clockRadius * 0.04); nvgLineTo(vg, 0, -clockRadius * 0.8); nvgStrokeWidth(vg, widthMedium); nvgStroke(vg); nvgRestore(vg); // Second hand nvgStrokeColor(vg, lightestColor); nvgSave(vg); nvgRotate(vg, secAngle); nvgBeginPath(vg); nvgMoveTo(vg, 0, clockRadius * 0.05); nvgLineTo(vg, 0, -clockRadius * 0.9); nvgStrokeWidth(vg, widthLight); nvgStroke(vg); nvgRestore(vg); }
int main() { constexpr auto width = 1200u; constexpr auto height = 800u; // init ny app auto& backend = ny::Backend::choose(); if(!backend.vulkan()) { dlg_error("ny backend has no vulkan support!"); return 0; } auto ac = backend.createAppContext(); // basic vpp init auto iniExtensions = ac->vulkanExtensions(); iniExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); vk::ApplicationInfo appInfo ("vpp-intro", 1, "vpp", 1, VK_API_VERSION_1_0); vk::InstanceCreateInfo instanceInfo; instanceInfo.pApplicationInfo = &appInfo; instanceInfo.enabledExtensionCount = iniExtensions.size(); instanceInfo.ppEnabledExtensionNames = iniExtensions.data(); #ifdef WithLayers constexpr auto layer = "VK_LAYER_LUNARG_standard_validation"; instanceInfo.enabledLayerCount = 1; instanceInfo.ppEnabledLayerNames = &layer; #endif vpp::Instance instance(instanceInfo); #ifdef WithLayers vpp::DebugCallback debugCallback(instance); #endif // ny init auto run = true; auto listener = MyWindowListener {}; listener.run = &run; auto vkSurface = vk::SurfaceKHR {}; auto ws = ny::WindowSettings {}; ws.surface = ny::SurfaceType::vulkan; ws.listener = &listener; ws.size = {width, height}; ws.vulkan.instance = (VkInstance) instance.vkHandle(); ws.vulkan.storeSurface = &(std::uintptr_t&) (vkSurface); auto wc = ac->createWindowContext(ws); // further vpp init const vpp::Queue* presentQueue; vpp::Device device(instance, vkSurface, presentQueue); vpp::Swapchain swapchain(device, vkSurface, {width, height}, {}); // vvg setup auto nvgContext = vvg::createContext(swapchain); auto font = nvgCreateFont(nvgContext, "sans", "Roboto-Regular.ttf"); using Clock = std::chrono::high_resolution_clock; auto lastFrameTimer = Clock::now(); unsigned int framesCount = 0; std::string fpsString = "420 fps"; // main loop while(run) { if(!ac->dispatchEvents()) break; nvgBeginFrame(nvgContext, width, height, width / (float) height); nvgBeginPath(nvgContext); nvgMoveTo(nvgContext, 10, 10); nvgLineTo(nvgContext, 10, 400); nvgLineTo(nvgContext, 100, 400); nvgQuadTo(nvgContext, 100, 50, 400, 120); nvgLineTo(nvgContext, 450, 10); nvgClosePath(nvgContext); nvgFillColor(nvgContext, nvgRGBAf(0.5, 0.8, 0.7, 1.0)); nvgFill(nvgContext); nvgBeginPath(nvgContext); nvgFontFaceId(nvgContext, font); nvgFontSize(nvgContext, 100.f); nvgFontBlur(nvgContext, .8f); nvgFillColor(nvgContext, nvgRGBAf(1.0, 1.0, 1.0, 1.0)); nvgTextBox(nvgContext, 200, 200, width - 200, "Hello Vulkan Vector Graphics World", nullptr); nvgFontSize(nvgContext, 30.f); nvgFontBlur(nvgContext, .2f); nvgText(nvgContext, 10, height - 20, fpsString.c_str(), nullptr); nvgBeginPath(nvgContext); nvgRect(nvgContext, 700, 400, 300, 300); nvgPathWinding(nvgContext, NVG_HOLE); nvgRect(nvgContext, 750, 450, 50, 50); // auto paint = nvgRadialGradient(nvgContext, 750, 425,20, 50, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0)); // auto paint = nvgRadialGradient(nvgContext, 0.0, 0.0, 0.2, 100.0, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0)); auto paint = nvgLinearGradient(nvgContext, 700, 400, 800, 450, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0)); nvgFillPaint(nvgContext, paint); // nvgFillColor(nvgContext, nvgRGBA(200, 200, 0, 200)); nvgClosePath(nvgContext); nvgFill(nvgContext); nvgEndFrame(nvgContext); // only refresh frame timer every second framesCount++; if(Clock::now() - lastFrameTimer >= std::chrono::seconds(1)) { fpsString = std::to_string(framesCount) + " fps"; lastFrameTimer = Clock::now(); framesCount = 0; } } vvg::destroyContext(*nvgContext); }
void Button::draw(NVGcontext * ctx) { Widget::draw(ctx); NVGcolor gradTop = mTheme->mButtonGradientTopUnfocused; NVGcolor gradBot = mTheme->mButtonGradientBotUnfocused; if (mPushed) { gradTop = mTheme->mButtonGradientTopPushed; gradBot = mTheme->mButtonGradientBotPushed; } else if (mMouseFocus && mEnabled) { gradTop = mTheme->mButtonGradientTopFocused; gradBot = mTheme->mButtonGradientBotFocused; } nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x + 1, mPos.y + 1.0f, mSize.x - 2, mSize.y - 2, mTheme->mButtonCornerRadius - 1); if (mBackgroundColor.a != 0) { nvgFillColor(ctx, Colour(mBackgroundColor.r, mBackgroundColor.g, mBackgroundColor.b, 1.f)); nvgFill(ctx); if (mPushed) gradTop.a = gradBot.a = 0.8f; else { double v = 1 - mBackgroundColor.a; gradTop.a = gradBot.a = mEnabled ? v : v * .5f + .5f; } } NVGpaint bg = nvgLinearGradient(ctx, mPos.x, mPos.y, mPos.x, mPos.y + mSize.y, gradTop, gradBot); nvgFillPaint(ctx, bg); nvgFill(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x + 0.5f, mPos.y + (mPushed ? 0.5f : 1.5f), mSize.x - 1, mSize.y - 1 - (mPushed ? 0.0f : 1.0f), mTheme->mButtonCornerRadius); nvgStrokeColor(ctx, mTheme->mBorderLight); nvgStroke(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x + 0.5f, mPos.y + 0.5f, mSize.x - 1, mSize.y - 2, mTheme->mButtonCornerRadius); nvgStrokeColor(ctx, mTheme->mBorderDark); nvgStroke(ctx); int fontSize = mFontSize == -1 ? mTheme->mButtonFontSize : mFontSize; nvgFontSize(ctx, fontSize); nvgFontFace(ctx, "sans-bold"); float tw = nvgTextBounds(ctx, 0, 0, mCaption.c_str(), nullptr, nullptr); vec2 center = vec2((float)mPos.x, (float)mPos.y) + vec2((float)mSize.x, (float)mSize.y) * 0.5f; vec2 textPos(center.x - tw * 0.5f, center.y - 1); NVGcolor textColor = mTextColor.a == 0 ? mTheme->mTextColor : mTextColor; if (!mEnabled) textColor = mTheme->mDisabledTextColor; if (mIcon) { auto icon = utf8(mIcon); float iw, ih = fontSize; if (nvgIsFontIcon(mIcon)) { ih *= 1.5f; nvgFontSize(ctx, ih); nvgFontFace(ctx, "icons"); iw = nvgTextBounds(ctx, 0, 0, icon.data(), nullptr, nullptr); } else { int w, h; ih *= 0.9f; nvgImageSize(ctx, mIcon, &w, &h); iw = w * ih / h; } if (mCaption != "") iw += mSize.y * 0.15f; nvgFillColor(ctx, textColor); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); vec2 iconPos = center; iconPos.y -= 1; if (mIconPosition == IconPosition::LeftCentered) { iconPos.x -= (tw + iw) * 0.5f; textPos.x += iw * 0.5f; } else if (mIconPosition == IconPosition::RightCentered) { textPos.x -= iw * 0.5f; iconPos.x += tw * 0.5f; } else if (mIconPosition == IconPosition::Left) iconPos.x = mPos.x + 8; else if (mIconPosition == IconPosition::Right) iconPos.x = mPos.x + mSize.x - iw - 8; if (nvgIsFontIcon(mIcon)) nvgText(ctx, iconPos.x, iconPos.y + 1, icon.data(), nullptr); else { NVGpaint imgPaint = nvgImagePattern(ctx, iconPos.x, iconPos.y - ih / 2, iw, ih, 0, mIcon, mEnabled ? 0.5f : 0.25f); nvgFillPaint(ctx, imgPaint); nvgFill(ctx); } } nvgFontSize(ctx, fontSize); nvgFontFace(ctx, "sans-bold"); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); nvgFillColor(ctx, mTheme->mTextColorShadow); nvgText(ctx, textPos.x, textPos.y, mCaption.c_str(), nullptr); nvgFillColor(ctx, textColor); nvgText(ctx, textPos.x, textPos.y + 1, mCaption.c_str(), nullptr); }
void drawGraph(struct NVGcontext* vg, float x, float y, float w, float h, float t) { struct NVGpaint bg; float samples[6]; float sx[6], sy[6]; float dx = w/5.0f; int i; samples[0] = (1+sinf(t*1.2345f+cosf(t*0.33457f)*0.44f) )*0.5f; samples[1] = (1+sinf(t*0.68363f+cosf(t*1.3f)*1.55f) )*0.5f; samples[2] = (1+sinf(t*1.1642f+cosf(t*0.33457f)*1.24f) )*0.5f; samples[3] = (1+sinf(t*0.56345f+cosf(t*1.63f)*0.14f) )*0.5f; samples[4] = (1+sinf(t*1.6245f+cosf(t*0.254f)*0.3f) )*0.5f; samples[5] = (1+sinf(t*0.345f+cosf(t*0.03f)*0.6f) )*0.5f; for (i = 0; i < 6; i++) { sx[i] = x+i*dx; sy[i] = y+h*samples[i]*0.8f; } // Graph background bg = nvgLinearGradient(vg, x,y,x,y+h, nvgRGBA(0,160,192,0), nvgRGBA(0,160,192,64) ); nvgBeginPath(vg); nvgMoveTo(vg, sx[0], sy[0]); for (i = 1; i < 6; i++) nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1], sx[i]-dx*0.5f,sy[i], sx[i],sy[i]); nvgLineTo(vg, x+w, y+h); nvgLineTo(vg, x, y+h); nvgFillPaint(vg, bg); nvgFill(vg); // Graph line nvgBeginPath(vg); nvgMoveTo(vg, sx[0], sy[0]+2); for (i = 1; i < 6; i++) nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1]+2, sx[i]-dx*0.5f,sy[i]+2, sx[i],sy[i]+2); nvgStrokeColor(vg, nvgRGBA(0,0,0,32) ); nvgStrokeWidth(vg, 3.0f); nvgStroke(vg); nvgBeginPath(vg); nvgMoveTo(vg, sx[0], sy[0]); for (i = 1; i < 6; i++) nvgBezierTo(vg, sx[i-1]+dx*0.5f,sy[i-1], sx[i]-dx*0.5f,sy[i], sx[i],sy[i]); nvgStrokeColor(vg, nvgRGBA(0,160,192,255) ); nvgStrokeWidth(vg, 3.0f); nvgStroke(vg); // Graph sample pos for (i = 0; i < 6; i++) { bg = nvgRadialGradient(vg, sx[i],sy[i]+2, 3.0f,8.0f, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,0) ); nvgBeginPath(vg); nvgRect(vg, sx[i]-10, sy[i]-10+2, 20,20); nvgFillPaint(vg, bg); nvgFill(vg); } nvgBeginPath(vg); for (i = 0; i < 6; i++) nvgCircle(vg, sx[i], sy[i], 4.0f); nvgFillColor(vg, nvgRGBA(0,160,192,255) ); nvgFill(vg); nvgBeginPath(vg); for (i = 0; i < 6; i++) nvgCircle(vg, sx[i], sy[i], 2.0f); nvgFillColor(vg, nvgRGBA(220,220,220,255) ); nvgFill(vg); nvgStrokeWidth(vg, 1.0f); }
void Button::draw(NVGcontext *ctx) { GUIObject::draw(ctx); NVGcolor gradTop = Theme.mButtonGradientTopUnfocused; NVGcolor gradBot = Theme.mButtonGradientBotUnfocused; if (mPushed) { gradTop = Theme.mButtonGradientTopPushed; gradBot = Theme.mButtonGradientBotPushed; } else if (mMouseFocus && mEnabled) { gradTop = Theme.mButtonGradientTopFocused; gradBot = Theme.mButtonGradientBotFocused; } nvgBeginPath(ctx); nvgRoundedRect(ctx, mPosition.x + 1, mPosition.y + 1, mSize.x - 2, mSize.y - 2, Theme.mButtonCornerRadius); if (mBackgroundColor.a != 0) { nvgFillColor(ctx, Color(mBackgroundColor.r, mBackgroundColor.g, mBackgroundColor.b, 1.f)); nvgFill(ctx); if (mPushed) { gradTop.a = gradBot.a = 0.8f; } else { double v = 1 - mBackgroundColor.a/2; gradTop.a = gradBot.a = mEnabled ? v : v * .5f + 0.5f; } } NVGpaint bg = nvgLinearGradient(ctx, mPosition.x, mPosition.y, mPosition.x, mPosition.y + mSize.y, gradTop, gradBot); nvgFillPaint(ctx, bg); nvgFill(ctx); // nvgBeginPath(ctx); // nvgRoundedRect(ctx, mPosition.x + 0.5f, mPosition.y + (mPushed ? 0.5f : 1.5f), mSize.x - 1, // mSize.y - 1 - (mPushed ? 0.0f : 1.0f), Theme.mButtonCornerRadius); // nvgStrokeColor(ctx, Theme.mBorderLight); // nvgStroke(ctx); // nvgBeginPath(ctx); // nvgRoundedRect(ctx, mPosition.x + 0.5f, mPosition.y + 0.5f, mSize.x - 1, // mSize.y - 2, Theme.mButtonCornerRadius); // nvgStrokeColor(ctx, Theme.mBorderDark); // nvgStroke(ctx); int fontSize = mFontSize == -1 ? Theme.mButtonFontSize : mFontSize; nvgFontSize(ctx, fontSize); nvgFontFace(ctx, "sans-bold"); float tw = nvgTextBounds(ctx, 0,0, mCaption.c_str(), nullptr, nullptr); vec2 center = (vec2)mPosition + ((vec2)mSize) * 0.5f; vec2 textPos(center.x - 0.5f * tw, center.y - 1); NVGcolor textColor = mTextColor.a == 0 ? Theme.mTextColor : mTextColor; // if (!mEnabled) // textColor = mDisabledTextColor; if (mIcon) { auto icon = utf8(mIcon); float iw, ih = fontSize; ih *= 1.5f; nvgFontSize(ctx, ih); nvgFontFace(ctx, "icons"); iw = nvgTextBounds(ctx, 0, 0, icon.data(), nullptr, nullptr); if (mCaption != "") iw += mSize.y * 0.15f; nvgFillColor(ctx, textColor); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); vec2 iconPos = center; iconPos.y -= 1; if (mIconPosition == IconPosition::LeftCentered) { iconPos.x -= (tw + iw) * 0.5f; textPos.x += iw * 0.5f; } else if (mIconPosition == IconPosition::RightCentered) { textPos.x -= iw * 0.5f; iconPos.x += tw * 0.5f; } else if (mIconPosition == IconPosition::Left) { iconPos.x = mPosition.x + 8; } else if (mIconPosition == IconPosition::Right) { iconPos.x = mPosition.x + mSize.x - iw - 8; } nvgText(ctx, iconPos.x, iconPos.y+1, icon.data(), nullptr); } nvgFontSize(ctx, fontSize); nvgFontFace(ctx, "sans-bold"); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); // nvgFillColor(ctx, Theme.mTextColorShadow); // nvgText(ctx, textPos.x, textPos.y, mCaption.c_str(), nullptr); nvgFillColor(ctx, textColor); nvgText(ctx, textPos.x, textPos.y + 1, mCaption.c_str(), nullptr); }
void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, const int* images, int nimages, float t) { float cornerRadius = 3.0f; struct NVGpaint shadowPaint, imgPaint, fadePaint; float ix,iy,iw,ih; float thumb = 60.0f; float arry = 30.5f; int imgw, imgh; float stackh = (nimages/2) * (thumb+10) + 10; int i; float u = (1+cosf(t*0.5f) )*0.5f; float scrollh; nvgSave(vg); // nvgClearState(vg); // Drop shadow shadowPaint = nvgBoxGradient(vg, x,y+4, w,h, cornerRadius*2, 20, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0) ); nvgBeginPath(vg); nvgRect(vg, x-10,y-10, w+20,h+30); nvgRoundedRect(vg, x,y, w,h, cornerRadius); nvgPathWinding(vg, NVG_HOLE); nvgFillPaint(vg, shadowPaint); nvgFill(vg); // Window nvgBeginPath(vg); nvgRoundedRect(vg, x,y, w,h, cornerRadius); nvgMoveTo(vg, x-10,y+arry); nvgLineTo(vg, x+1,y+arry-11); nvgLineTo(vg, x+1,y+arry+11); nvgFillColor(vg, nvgRGBA(200,200,200,255) ); nvgFill(vg); nvgSave(vg); nvgScissor(vg, x,y,w,h); nvgTranslate(vg, 0, -(stackh - h)*u); for (i = 0; i < nimages; i++) { float tx, ty; tx = x+10; ty = y+10; tx += (i%2) * (thumb+10); ty += (i/2) * (thumb+10); nvgImageSize(vg, images[i], &imgw, &imgh); if (imgw < imgh) { iw = thumb; ih = iw * (float)imgh/(float)imgw; ix = 0; iy = -(ih-thumb)*0.5f; } else { ih = thumb; iw = ih * (float)imgw/(float)imgh; ix = -(iw-thumb)*0.5f; iy = 0; } imgPaint = nvgImagePattern(vg, tx+ix, ty+iy, iw,ih, 0.0f/180.0f*NVG_PI, images[i], 0); nvgBeginPath(vg); nvgRoundedRect(vg, tx,ty, thumb,thumb, 5); nvgFillPaint(vg, imgPaint); nvgFill(vg); shadowPaint = nvgBoxGradient(vg, tx-1,ty, thumb+2,thumb+2, 5, 3, nvgRGBA(0,0,0,128), nvgRGBA(0,0,0,0) ); nvgBeginPath(vg); nvgRect(vg, tx-5,ty-5, thumb+10,thumb+10); nvgRoundedRect(vg, tx,ty, thumb,thumb, 6); nvgPathWinding(vg, NVG_HOLE); nvgFillPaint(vg, shadowPaint); nvgFill(vg); nvgBeginPath(vg); nvgRoundedRect(vg, tx+0.5f,ty+0.5f, thumb-1,thumb-1, 4-0.5f); nvgStrokeWidth(vg,1.0f); nvgStrokeColor(vg, nvgRGBA(255,255,255,192) ); nvgStroke(vg); } nvgRestore(vg); // Hide fades fadePaint = nvgLinearGradient(vg, x,y,x,y+6, nvgRGBA(200,200,200,255), nvgRGBA(200,200,200,0) ); nvgBeginPath(vg); nvgRect(vg, x+4,y,w-8,6); nvgFillPaint(vg, fadePaint); nvgFill(vg); fadePaint = nvgLinearGradient(vg, x,y+h,x,y+h-6, nvgRGBA(200,200,200,255), nvgRGBA(200,200,200,0) ); nvgBeginPath(vg); nvgRect(vg, x+4,y+h-6,w-8,6); nvgFillPaint(vg, fadePaint); nvgFill(vg); // Scroll bar shadowPaint = nvgBoxGradient(vg, x+w-12+1,y+4+1, 8,h-8, 3,4, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,92) ); nvgBeginPath(vg); nvgRoundedRect(vg, x+w-12,y+4, 8,h-8, 3); nvgFillPaint(vg, shadowPaint); // nvgFillColor(vg, nvgRGBA(255,0,0,128) ); nvgFill(vg); scrollh = (h/stackh) * (h-8); shadowPaint = nvgBoxGradient(vg, x+w-12-1,y+4+(h-8-scrollh)*u-1, 8,scrollh, 3,4, nvgRGBA(220,220,220,255), nvgRGBA(128,128,128,255) ); nvgBeginPath(vg); nvgRoundedRect(vg, x+w-12+1,y+4+1 + (h-8-scrollh)*u, 8-2,scrollh-2, 2); nvgFillPaint(vg, shadowPaint); // nvgFillColor(vg, nvgRGBA(0,0,0,128) ); nvgFill(vg); nvgRestore(vg); }
static void draw(NVGcontext *nvg, struct zr_command_queue *queue, int width, int height) { const struct zr_command *cmd; glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glEnable(GL_TEXTURE_2D); nvgBeginFrame(nvg, width, height, ((float)width/(float)height)); zr_foreach_command(cmd, queue) { switch (cmd->type) { case ZR_COMMAND_NOP: break; case ZR_COMMAND_SCISSOR: { const struct zr_command_scissor *s = zr_command(scissor, cmd); nvgScissor(nvg, s->x, s->y, s->w, s->h); } break; case ZR_COMMAND_LINE: { const struct zr_command_line *l = zr_command(line, cmd); nvgBeginPath(nvg); nvgMoveTo(nvg, l->begin.x, l->begin.y); nvgLineTo(nvg, l->end.x, l->end.y); nvgFillColor(nvg, nvgRGBA(l->color.r, l->color.g, l->color.b, l->color.a)); nvgFill(nvg); } break; case ZR_COMMAND_CURVE: { const struct zr_command_curve *q = zr_command(curve, cmd); nvgBeginPath(nvg); nvgMoveTo(nvg, q->begin.x, q->begin.y); nvgBezierTo(nvg, q->ctrl[0].x, q->ctrl[0].y, q->ctrl[1].x, q->ctrl[1].y, q->end.x, q->end.y); nvgStrokeColor(nvg, nvgRGBA(q->color.r, q->color.g, q->color.b, q->color.a)); nvgStroke(nvg); } break; case ZR_COMMAND_RECT: { const struct zr_command_rect *r = zr_command(rect, cmd); nvgBeginPath(nvg); nvgRoundedRect(nvg, r->x, r->y, r->w, r->h, r->rounding); nvgFillColor(nvg, nvgRGBA(r->color.r, r->color.g, r->color.b, r->color.a)); nvgFill(nvg); } break; case ZR_COMMAND_CIRCLE: { const struct zr_command_circle *c = zr_command(circle, cmd); nvgBeginPath(nvg); nvgCircle(nvg, c->x + (c->w/2.0f), c->y + c->w/2.0f, c->w/2.0f); nvgFillColor(nvg, nvgRGBA(c->color.r, c->color.g, c->color.b, c->color.a)); nvgFill(nvg); } break; case ZR_COMMAND_TRIANGLE: { const struct zr_command_triangle *t = zr_command(triangle, cmd); nvgBeginPath(nvg); nvgMoveTo(nvg, t->a.x, t->a.y); nvgLineTo(nvg, t->b.x, t->b.y); nvgLineTo(nvg, t->c.x, t->c.y); nvgLineTo(nvg, t->a.x, t->a.y); nvgFillColor(nvg, nvgRGBA(t->color.r, t->color.g, t->color.b, t->color.a)); nvgFill(nvg); } break; case ZR_COMMAND_TEXT: { const struct zr_command_text *t = zr_command(text, cmd); nvgBeginPath(nvg); nvgRoundedRect(nvg, t->x, t->y, t->w, t->h, 0); nvgFillColor(nvg, nvgRGBA(t->background.r, t->background.g, t->background.b, t->background.a)); nvgFill(nvg); nvgBeginPath(nvg); nvgFillColor(nvg, nvgRGBA(t->foreground.r, t->foreground.g, t->foreground.b, t->foreground.a)); nvgTextAlign(nvg, NVG_ALIGN_MIDDLE); nvgText(nvg, t->x, t->y + t->h * 0.5f, t->string, &t->string[t->length]); nvgFill(nvg); } break; case ZR_COMMAND_IMAGE: { const struct zr_command_image *i = zr_command(image, cmd); NVGpaint imgpaint; imgpaint = nvgImagePattern(nvg, i->x, i->y, i->w, i->h, 0, i->img.handle.id, 1.0f); nvgBeginPath(nvg); nvgRoundedRect(nvg, i->x, i->y, i->w, i->h, 0); nvgFillPaint(nvg, imgpaint); nvgFill(nvg); } break; case ZR_COMMAND_ARC: default: break; } } zr_command_queue_clear(queue); nvgResetScissor(nvg); nvgEndFrame(nvg); glPopAttrib(); }
void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float height, float mx, float my) { struct NVGtextRow rows[3]; struct NVGglyphPosition glyphs[100]; const char* text = "This is longer chunk of text.\n \n Would have used lorem ipsum but she was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party."; const char* start; const char* end; int nrows, i, nglyphs, j, lnum = 0; float lineh; float caretx, px; float bounds[4]; float gx = 0.0f, gy = 0.0f; int gutter = 0; NVG_NOTUSED(height); nvgSave(vg); nvgFontSize(vg, 18.0f); nvgFontFace(vg, "sans"); nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); nvgTextMetrics(vg, NULL, NULL, &lineh); // The text break API can be used to fill a large buffer of rows, // or to iterate over the text just few lines (or just one) at a time. // The "next" variable of the last returned item tells where to continue. start = text; end = text + strlen(text); for (nrows = nvgTextBreakLines(vg, start, end, width, rows, 3); 0 != nrows; nrows = nvgTextBreakLines(vg, start, end, width, rows, 3) ) { for (i = 0; i < nrows; i++) { struct NVGtextRow* row = &rows[i]; int hit = mx > x && mx < (x+width) && my >= y && my < (y+lineh); nvgBeginPath(vg); nvgFillColor(vg, nvgRGBA(255,255,255,hit?64:8) ); nvgRect(vg, x, y, row->width, lineh); nvgFill(vg); nvgFillColor(vg, nvgRGBA(255,255,255,255) ); nvgText(vg, x, y, row->start, row->end); if (hit) { caretx = (mx < x+row->width/2) ? x : x+row->width; px = x; nglyphs = nvgTextGlyphPositions(vg, x, y, row->start, row->end, glyphs, 100); for (j = 0; j < nglyphs; j++) { float x0 = glyphs[j].x; float x1 = (j+1 < nglyphs) ? glyphs[j+1].x : x+row->width; float tgx = x0 * 0.3f + x1 * 0.7f; if (mx >= px && mx < tgx) caretx = glyphs[j].x; px = tgx; } nvgBeginPath(vg); nvgFillColor(vg, nvgRGBA(255,192,0,255) ); nvgRect(vg, caretx, y, 1, lineh); nvgFill(vg); gutter = lnum+1; gx = x - 10; gy = y + lineh/2; } lnum++; y += lineh; } // Keep going... start = rows[nrows-1].next; } if (gutter) { char txt[16]; bx::snprintf(txt, sizeof(txt), "%d", gutter); nvgFontSize(vg, 13.0f); nvgTextAlign(vg, NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE); nvgTextBounds(vg, gx,gy, txt, NULL, bounds); nvgBeginPath(vg); nvgFillColor(vg, nvgRGBA(255,192,0,255) ); nvgRoundedRect(vg , bx::fround(bounds[0])-4.0f , bx::fround(bounds[1])-2.0f , bx::fround(bounds[2]-bounds[0])+8.0f , bx::fround(bounds[3]-bounds[1])+4.0f , (bx::fround(bounds[3]-bounds[1])+4.0f)/2.0f-1.0f ); nvgFill(vg); nvgFillColor(vg, nvgRGBA(32,32,32,255) ); nvgText(vg, gx,gy, txt, NULL); } y += 20.0f; nvgFontSize(vg, 13.0f); nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); nvgTextLineHeight(vg, 1.2f); nvgTextBoxBounds(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL, bounds); nvgBeginPath(vg); nvgFillColor(vg, nvgRGBA(220,220,220,255) ); nvgRoundedRect(vg , bx::fround(bounds[0]-2.0f) , bx::fround(bounds[1]-2.0f) , bx::fround(bounds[2]-bounds[0])+4.0f , bx::fround(bounds[3]-bounds[1])+4.0f , 3.0f ); px = float( (int)( (bounds[2]+bounds[0])/2) ); nvgMoveTo(vg, px,bounds[1] - 10); nvgLineTo(vg, px+7,bounds[1]+1); nvgLineTo(vg, px-7,bounds[1]+1); nvgFill(vg); nvgFillColor(vg, nvgRGBA(0,0,0,220) ); nvgTextBox(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL); nvgRestore(vg); }
void renderGraph(NVGcontext* vg, float x, float y, PerfGraph* fps) { int i; float avg, w, h; char str[64]; avg = getGraphAverage(fps); w = 200; h = 35; nvgBeginPath(vg); nvgRect(vg, x,y, w,h); nvgFillColor(vg, nvgRGBA(0,0,0,128)); nvgFill(vg); nvgBeginPath(vg); nvgMoveTo(vg, x, y+h); if (fps->style == GRAPH_RENDER_FPS) { for (i = 0; i < GRAPH_HISTORY_COUNT; i++) { float v = 1.0f / (0.00001f + fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT]); float vx, vy; if (v > 80.0f) v = 80.0f; vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w; vy = y + h - ((v / 80.0f) * h); nvgLineTo(vg, vx, vy); } } else if (fps->style == GRAPH_RENDER_PERCENT) { for (i = 0; i < GRAPH_HISTORY_COUNT; i++) { float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1.0f; float vx, vy; if (v > 100.0f) v = 100.0f; vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w; vy = y + h - ((v / 100.0f) * h); nvgLineTo(vg, vx, vy); } } else { for (i = 0; i < GRAPH_HISTORY_COUNT; i++) { float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1000.0f; float vx, vy; if (v > 20.0f) v = 20.0f; vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w; vy = y + h - ((v / 20.0f) * h); nvgLineTo(vg, vx, vy); } } nvgLineTo(vg, x+w, y+h); nvgFillColor(vg, nvgRGBA(255,192,0,128)); nvgFill(vg); nvgFontFace(vg, "sans"); if (fps->name[0] != '\0') { nvgFontSize(vg, 14.0f); nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(240,240,240,192)); nvgText(vg, x+3,y+1, fps->name, NULL); } if (fps->style == GRAPH_RENDER_FPS) { nvgFontSize(vg, 18.0f); nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(240,240,240,255)); sprintf(str, "%.2f FPS", 1.0f / avg); nvgText(vg, x+w-3,y+1, str, NULL); nvgFontSize(vg, 15.0f); nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BOTTOM); nvgFillColor(vg, nvgRGBA(240,240,240,160)); sprintf(str, "%.2f ms", avg * 1000.0f); nvgText(vg, x+w-3,y+h-1, str, NULL); } else if (fps->style == GRAPH_RENDER_PERCENT) { nvgFontSize(vg, 18.0f); nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(240,240,240,255)); sprintf(str, "%.1f %%", avg * 1.0f); nvgText(vg, x+w-3,y+1, str, NULL); } else { nvgFontSize(vg, 18.0f); nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(240,240,240,255)); sprintf(str, "%.2f ms", avg * 1000.0f); nvgText(vg, x+w-3,y+1, str, NULL); } }
void OGUITextInput::draw(int x, int y, int w) { int h = this->height; OGUIWidget::draw(x, y, w); OGUIArea* area= (OGUIArea*)(this->area); NVGcontext* vg= (NVGcontext*)(area->window->vg); NVGpaint bg; // Edit bg = nvgBoxGradient(vg, x+1,y+1+1.5f, w-2,h-2, 3,4, nvgRGBA(255,255,255,32), nvgRGBA(32,32,32,32)); nvgBeginPath(vg); nvgRoundedRect(vg, x+1,y+1, w-2,h-2, 4-1); nvgFillPaint(vg, bg); nvgFill(vg); nvgBeginPath(vg); nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, 4-0.5f); nvgStrokeColor(vg, nvgRGBA(0,0,0,48)); nvgStroke(vg); nvgFontSize(vg, 20.0f*area->window->font_scale); nvgFontFace(vg, "sans"); if(value.compare(label)==0) nvgFillColor(vg, nvgRGBA(255,255,255,64)); else nvgFillColor(vg, nvgRGBA(255,255,255,128)); nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); nvgText(vg, x+h*0.3f,y+h*0.5f, value.c_str(), NULL); if(area->window->mouse_x > x && area->window->mouse_x < x+w && area->window->mouse_y > y && area->window->mouse_y < y + h ) { area->window->setCursor(TEXT_CURSOR); if (area->window->mouse_state == GLFW_PRESS) { is_focus_= true; area->window->setKeyFocus(this); if(value.compare(label)==0) value=""; } }else{ area->window->setCursor(DEFAULT_CURSOR); if (area->window->mouse_state == GLFW_PRESS) { if(value.compare("")==0) value= string(label); is_focus_= false; } } if(is_focus_){ float char_pos= nvgTextBounds(vg, x, y, value.c_str(), NULL, NULL); nvgBeginPath(vg); animation_alpha_+=10; animation_alpha_=animation_alpha_%255; nvgFillColor(vg, nvgRGBA(255,192,0,animation_alpha_)); nvgRect(vg, x+h*0.3f+char_pos, y+6, 1, 20); nvgFill(vg); } }
void TextBox::draw(NVGcontext* ctx) { Widget::draw(ctx); NVGpaint bg = nvgBoxGradient(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3, 4, Color(255, 32), Color(32, 32)); NVGpaint fg1 = nvgBoxGradient(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3, 4, Color(150, 32), Color(32, 32)); NVGpaint fg2 = nvgBoxGradient(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3, 4, nvgRGBA(255, 0, 0, 100), nvgRGBA(255, 0, 0, 50)); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3); if(mEditable && focused()) mValidFormat ? nvgFillPaint(ctx, fg1) : nvgFillPaint(ctx, fg2); else nvgFillPaint(ctx, bg); nvgFill(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 0.5f, mPos.y() + 0.5f, mSize.x() - 1, mSize.y() - 1, 2.5f); nvgStrokeColor(ctx, Color(0, 48)); nvgStroke(ctx); nvgFontSize(ctx, fontSize()); nvgFontFace(ctx, "sans"); Vector2i drawPos(mPos.x(), mPos.y() + mSize.y() * 0.5f + 1); float xSpacing = mSize.y() * 0.3f; float unitWidth = 0; if (mUnitsImage > 0) { int w, h; nvgImageSize(ctx, mUnitsImage, &w, &h); float unitHeight = mSize.y() * 0.4f; unitWidth = w * unitHeight / h; NVGpaint imgPaint = nvgImagePattern( ctx, mPos.x() + mSize.x() - xSpacing - unitWidth, drawPos.y() - unitHeight * 0.5f, unitWidth, unitHeight, 0, mUnitsImage, mEnabled ? 0.7f : 0.35f); nvgBeginPath(ctx); nvgRect(ctx, mPos.x() + mSize.x() - xSpacing - unitWidth, drawPos.y() - unitHeight * 0.5f, unitWidth, unitHeight); nvgFillPaint(ctx, imgPaint); nvgFill(ctx); unitWidth += 2; } else if (!mUnits.empty()) { unitWidth = nvgTextBounds(ctx, 0, 0, mUnits.c_str(), nullptr, nullptr); nvgFillColor(ctx, Color(255, mEnabled ? 64 : 32)); nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE); nvgText(ctx, mPos.x() + mSize.x() - xSpacing, drawPos.y(), mUnits.c_str(), nullptr); unitWidth += 2; } switch (mAlignment) { case Alignment::Left: nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); drawPos.x() += xSpacing; break; case Alignment::Right: nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE); drawPos.x() += mSize.x() - unitWidth - xSpacing; break; case Alignment::Center: nvgTextAlign(ctx, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE); drawPos.x() += mSize.x() * 0.5f; break; } nvgFontSize(ctx, fontSize()); nvgFillColor(ctx, mEnabled ? mTheme->mTextColor : mTheme->mDisabledTextColor); // clip visible text area float clipX = mPos.x() + xSpacing - 1.0f; float clipY = mPos.y() + 1.0f; float clipWidth = mSize.x() - unitWidth - 2 * xSpacing + 2.0f; float clipHeight = mSize.y() - 3.0f; nvgScissor(ctx, clipX, clipY, clipWidth, clipHeight); Vector2i oldDrawPos(drawPos); drawPos.x() += mTextOffset; if (mCommitted) { nvgText(ctx, drawPos.x(), drawPos.y(), mValue.c_str(), nullptr); } else { const int maxGlyphs = 1024; NVGglyphPosition glyphs[maxGlyphs]; float textBound[4]; nvgTextBounds(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, textBound); float lineh = textBound[3] - textBound[1]; // find cursor positions int nglyphs = nvgTextGlyphPositions(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, glyphs, maxGlyphs); updateCursor(ctx, textBound[2], glyphs, nglyphs); // compute text offset int prevCPos = mCursorPos > 0 ? mCursorPos - 1 : 0; int nextCPos = mCursorPos < nglyphs ? mCursorPos + 1 : nglyphs; float prevCX = cursorIndex2Position(prevCPos, textBound[2], glyphs, nglyphs); float nextCX = cursorIndex2Position(nextCPos, textBound[2], glyphs, nglyphs); if (nextCX > clipX + clipWidth) mTextOffset -= nextCX - (clipX + clipWidth) + 1; if (prevCX < clipX) mTextOffset += clipX - prevCX + 1; drawPos.x() = oldDrawPos.x() + mTextOffset; // draw text with offset nvgText(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr); nvgTextBounds(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, textBound); // recompute cursor positions nglyphs = nvgTextGlyphPositions(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, glyphs, maxGlyphs); if (mCursorPos > -1) { if (mSelectionPos > -1) { float caretx = cursorIndex2Position(mCursorPos, textBound[2], glyphs, nglyphs); float selx = cursorIndex2Position(mSelectionPos, textBound[2], glyphs, nglyphs); if (caretx > selx) std::swap(caretx, selx); // draw selection nvgBeginPath(ctx); nvgFillColor(ctx, nvgRGBA(255, 255, 255, 80)); nvgRect(ctx, caretx, drawPos.y() - lineh * 0.5f, selx - caretx, lineh); nvgFill(ctx); } float caretx = cursorIndex2Position(mCursorPos, textBound[2], glyphs, nglyphs); // draw cursor nvgBeginPath(ctx); nvgMoveTo(ctx, caretx, drawPos.y() - lineh * 0.5f); nvgLineTo(ctx, caretx, drawPos.y() + lineh * 0.5f); nvgStrokeColor(ctx, nvgRGBA(255, 192, 0, 255)); nvgStrokeWidth(ctx, 1.0f); nvgStroke(ctx); } } nvgResetScissor(ctx); }
void OGUIFileBrowser::draw() { // ToDo (damiles): Create scroll for more files in window if (_is_file_browser_visible) { NVGcontext *vg = (NVGcontext *) _window->vg; nvgBeginPath(vg); nvgRect(vg, 0, 0, _window->getWindowWidth(), _window->getWindowHeight()); nvgFillColor(vg, nvgRGBA(28, 30, 34, 255)); nvgFill(vg); // sep line nvgBeginPath(vg); nvgMoveTo(vg, 200, 40); nvgLineTo(vg, 200, _window->getWindowHeight()); nvgFillColor(vg, nvgRGBA(0,0,0,255)); nvgFill(vg); nvgBeginPath(vg); nvgMoveTo(vg, 0, 40); nvgLineTo(vg, _window->getWindowWidth(), 40); nvgFillColor(vg, nvgRGBA(0,0,0,255)); nvgFill(vg); nvgBeginPath(vg); nvgMoveTo(vg, 200, _window->getWindowHeight()-40); nvgLineTo(vg, _window->getWindowWidth(), _window->getWindowHeight()-40); nvgFillColor(vg, nvgRGBA(0,0,0,255)); nvgFill(vg); // Draw accept and cancel buttons if(drawBasicButton(vg, this->_window, "Accept", _window->getWindowWidth()-100, _window->getWindowHeight()-30, 90, 20, _window->mouse_x, _window->mouse_y)){ _is_file_browser_visible=0; } if(drawBasicButton(vg, this->_window, "Close", _window->getWindowWidth()-200, _window->getWindowHeight()-30, 90, 20, _window->mouse_x, _window->mouse_y)){ _file_browser_result= NULL; _is_file_browser_visible=0; } // Draw de devices we found drawHeader(vg, "System", 0, 40, 200); // Draw system files int x=10; int y=75; for(int i=0; i<_system.size(); i++){ OGUIFile *file= _system.at(i); if( file->draw(vg, x, y, _window->mouse_x, _window->mouse_y) ){ // is clicked _file_browser_result= file; if(_file_browser_result!=NULL) { if (_file_browser_result->_is_dir && _actual_folder.compare(_file_browser_result->_path) != 0) { readFolder(_file_browser_result->_path); _actual_folder= _file_browser_result->_path; _file_browser_result = NULL; } } } y+=22; } // Draw files x=210; y=50; int max_height= _window->getWindowHeight()-80; for(int i=0; i<_file_list.size(); i++){ OGUIFile *file= _file_list.at(i); if( file->draw(vg, x, y, _window->mouse_x, _window->mouse_y) ){ // is clicked _file_browser_result= file; if(_file_browser_result!=NULL) { if (_file_browser_result->_is_dir && _actual_folder.compare(_file_browser_result->_path) != 0) { readFolder(_file_browser_result->_path); _actual_folder= _file_browser_result->_path; _file_browser_result = NULL; } } } y+=22; if(y>=max_height){ x+=202; y=50; } } // Show icon in header nvgFontSize(vg, 16.0f); nvgFontFace(vg, "icons"); nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(0,0,0,255)); nvgText(vg, 10, 11, "\uF115", NULL); nvgFillColor(vg, nvgRGBA(255, 255, 255, 255)); nvgText(vg, 11, 13, "\uF115", NULL); nvgFillColor(vg, nvgRGBA(255,255,255,255)); // show path in header nvgFontSize(vg, 18.0f); nvgFontFace(vg, "sans-bold"); nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(0, 0, 0, 255)); nvgText(vg, 35, 10, resolved_path, NULL); nvgFillColor(vg, nvgRGBA(255, 255, 255, 255)); nvgText(vg, 36, 12, resolved_path, NULL); if(_file_browser_result!=NULL) { if (_file_browser_result->_is_dir == false) { // show file in footer nvgFontSize(vg, 18.0f); nvgFontFace(vg, "sans-bold"); nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); nvgFillColor(vg, nvgRGBA(0, 0, 0, 255)); nvgText(vg, 209, _window->getWindowHeight()-32, _file_browser_result->_file_name.c_str(), NULL); nvgFillColor(vg, nvgRGBA(255, 255, 255, 255)); nvgText(vg, 210, _window->getWindowHeight()-30, _file_browser_result->_file_name.c_str(), NULL); // Draw preview if its image if(_file_browser_result->isImage()){ x=0; y=_window->getWindowHeight()-200; drawHeader(vg, "Preview", 0, y-30, 200); int w=200; int h=200; NVGpaint bg; // Box bg = nvgBoxGradient(vg, x+1,y+1+1.5f, w-2,h-2, 3,4, nvgRGBA(255,255,255,32), nvgRGBA(32,32,32,32)); nvgBeginPath(vg); nvgRoundedRect(vg, x+1,y+1, w-2,h-2, 4-1); nvgFillPaint(vg, bg); nvgFill(vg); nvgBeginPath(vg); nvgRoundedRect(vg, x+0.5f,y+0.5f, w-1,h-1, 4-0.5f); nvgStrokeColor(vg, nvgRGBA(0,0,0,48)); nvgStroke(vg); // Image preview if(_preview_image==-1){ _preview_image= nvgCreateImageRGBA(vg, 150, 150, 0, _file_browser_result->getPreview()); }else{ nvgUpdateImage(vg, _preview_image, _file_browser_result->getPreview()); } NVGpaint imgPaint = nvgImagePattern(vg, 25, y+25, 150, 150, 0, _preview_image, 1); nvgBeginPath(vg); nvgRect(vg, 25, y+25, 150,150); nvgFillPaint(vg, imgPaint); nvgFill(vg); } } } } }
void vsLine(NVGcontext *vg) { nvgFill(vg); }
void Window::draw(NVGcontext *ctx) { int ds = mTheme->mWindowDropShadowSize, cr = mTheme->mWindowCornerRadius; int hh = mTheme->mWindowHeaderHeight; /* Draw window */ nvgSave(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr); nvgFillColor(ctx, mMouseFocus ? mTheme->mWindowFillFocused : mTheme->mWindowFillUnfocused); nvgFill(ctx); /* Draw a drop shadow */ NVGpaint shadowPaint = nvgBoxGradient( ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr*2, ds*2, mTheme->mDropShadow, mTheme->mTransparent); nvgBeginPath(ctx); nvgRect(ctx, mPos.x()-ds,mPos.y()-ds, mSize.x()+2*ds, mSize.y()+2*ds); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr); nvgPathWinding(ctx, NVG_HOLE); nvgFillPaint(ctx, shadowPaint); nvgFill(ctx); if (!mTitle.empty()) { /* Draw header */ NVGpaint headerPaint = nvgLinearGradient( ctx, mPos.x(), mPos.y(), mPos.x(), mPos.y() + hh, mTheme->mWindowHeaderGradientTop, mTheme->mWindowHeaderGradientBot); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), hh, cr); nvgFillPaint(ctx, headerPaint); nvgFill(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), hh, cr); nvgStrokeColor(ctx, mTheme->mWindowHeaderSepTop); nvgScissor(ctx, mPos.x(), mPos.y(), mSize.x(), 0.5f); nvgStroke(ctx); nvgResetScissor(ctx); nvgBeginPath(ctx); nvgMoveTo(ctx, mPos.x() + 0.5f, mPos.y() + hh - 1.5f); nvgLineTo(ctx, mPos.x() + mSize.x() - 0.5f, mPos.y() + hh - 1.5); nvgStrokeColor(ctx, mTheme->mWindowHeaderSepBot); nvgStroke(ctx); nvgFontSize(ctx, 18.0f); nvgFontFace(ctx, "sans-bold"); nvgTextAlign(ctx, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE); nvgFontBlur(ctx, 2); nvgFillColor(ctx, mTheme->mDropShadow); nvgText(ctx, mPos.x() + mSize.x() / 2, mPos.y() + hh / 2, mTitle.c_str(), nullptr); nvgFontBlur(ctx, 0); nvgFillColor(ctx, mFocused ? mTheme->mWindowTitleFocused : mTheme->mWindowTitleUnfocused); nvgText(ctx, mPos.x() + mSize.x() / 2, mPos.y() + hh / 2 - 1, mTitle.c_str(), nullptr); } nvgRestore(ctx); Widget::draw(ctx); }
void QNanoPainter::fill() { nvgFill(nvgCtx()); }
void GraphPane::draw(AlloyContext* context) { Region::draw(context); box2px rbounds = getBounds(); NVGcontext* nvg = context->nvgContext; box2px gbounds = rbounds; const float LARGE_TEXT = 18.0f; const float MEDIUM_TEXT = 16.0f; const float SMALL_TEXT = 12.0f; float2 gpos(-1, -1); gbounds.position = pixel2(rbounds.position.x + GRAPH_PADDING, rbounds.position.y + GRAPH_PADDING); gbounds.dimensions = pixel2(rbounds.dimensions.x - GRAPH_PADDING * 2, rbounds.dimensions.y - GRAPH_PADDING * 2); if (graphBounds.dimensions.x < 0 || graphBounds.dimensions.y < 0) { updateGraphBounds(); } nvgBeginPath(nvg); nvgRoundedRect(nvg, gbounds.position.x - 2, gbounds.position.y - 2, gbounds.dimensions.x + 4, gbounds.dimensions.y + 4, context->theme.CORNER_RADIUS); nvgFillColor(nvg, context->theme.LIGHTEST); nvgFill(nvg); //Draw vertical line for x=0 if (graphBounds.position.x < 0 && graphBounds.position.x + graphBounds.dimensions.x > 0) { float xpos = -graphBounds.position.x / graphBounds.dimensions.x; nvgBeginPath(nvg); nvgMoveTo(nvg, xpos * gbounds.dimensions.x + gbounds.position.x, gbounds.position.y); nvgLineTo(nvg, xpos * gbounds.dimensions.x + gbounds.position.x, gbounds.position.y + gbounds.dimensions.y); nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.75f)); nvgStroke(nvg); } //Draw horizontal line for y=0 if (graphBounds.position.y < 0 && graphBounds.position.y + graphBounds.dimensions.y > 0) { float ypos = -graphBounds.position.y / graphBounds.dimensions.y; nvgBeginPath(nvg); nvgMoveTo(nvg, gbounds.position.x, ypos * gbounds.dimensions.y + gbounds.position.y); nvgLineTo(nvg, gbounds.position.x + gbounds.dimensions.x, ypos * gbounds.dimensions.y + gbounds.position.y); nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.75f)); nvgStroke(nvg); } if (gbounds.contains(cursorPosition)) { context->setCursor(&Cursor::CrossHairs); gpos = (cursorPosition - gbounds.position) / gbounds.dimensions; gpos.y = 1 - gpos.y; gpos = gpos * graphBounds.dimensions + graphBounds.position; nvgBeginPath(nvg); nvgMoveTo(nvg, cursorPosition.x, gbounds.position.y); nvgLineTo(nvg, cursorPosition.x, gbounds.position.y + gbounds.dimensions.y); nvgStrokeWidth(nvg, 1.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.25f)); nvgStroke(nvg); nvgBeginPath(nvg); nvgMoveTo(nvg, gbounds.position.x, cursorPosition.y); nvgLineTo(nvg, gbounds.position.x + gbounds.dimensions.x, cursorPosition.y); nvgStrokeWidth(nvg, 1.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.25f)); nvgStroke(nvg); } for (GraphDataPtr& curve : curves) { std::vector<float2> points = curve->points; if (points.size() > 1 && graphBounds.dimensions.x > 0.0f && graphBounds.dimensions.y > 0.0f) { NVGcontext* nvg = context->nvgContext; float2 last = points[0]; last = (last - graphBounds.position) / graphBounds.dimensions; last.y = 1.0f - last.y; last = last * gbounds.dimensions + gbounds.position; nvgBeginPath(nvg); nvgMoveTo(nvg, last.x, last.y); for (int i = 1; i < (int)points.size(); i++) { float2 pt = points[i]; pt = (pt - graphBounds.position) / graphBounds.dimensions; pt.y = 1.0f - pt.y; pt = pt * gbounds.dimensions + gbounds.position; nvgLineTo(nvg, pt.x, pt.y); last = pt; } nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, curve->color); nvgStroke(nvg); } } nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); nvgFontSize(nvg, LARGE_TEXT); nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(rbounds.dimensions.x / 2, 2.0f), name, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgFontSize(nvg, MEDIUM_TEXT); nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM); drawText(nvg, rbounds.position + float2(rbounds.dimensions.x / 2, rbounds.dimensions.y - 4.0f), xAxisLabel, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); nvgSave(nvg); pixel2 center = rbounds.position + float2(2.0f, rbounds.dimensions.y * 0.5f); nvgTranslate(nvg, center.x, center.y); nvgRotate(nvg, -ALY_PI * 0.5f); drawText(nvg, pixel2(0, 2), yAxisLabel, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgRestore(nvg); nvgFontSize(nvg, SMALL_TEXT); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(GRAPH_PADDING, GRAPH_PADDING), MakeString() << std::setprecision(2) << (graphBounds.position.y + graphBounds.dimensions.y), FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); drawText(nvg, rbounds.position + float2(GRAPH_PADDING, rbounds.dimensions.y - GRAPH_PADDING), MakeString() << std::setprecision(2) << graphBounds.position.y, FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(rbounds.dimensions.x - GRAPH_PADDING, rbounds.dimensions.y - GRAPH_PADDING + 2), MakeString() << std::setprecision(2) << (graphBounds.position.x + graphBounds.dimensions.x), FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(GRAPH_PADDING, rbounds.dimensions.y - GRAPH_PADDING + 2), MakeString() << std::setprecision(2) << graphBounds.position.x, FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); if (cursorPosition.x >= 0) { float minDist = 1E30f; float bestY = 0; GraphDataPtr closestCurve; for (GraphDataPtr& curve : curves) { float y = curve->interpolate(gpos.x); if (y != GraphData::NO_INTERSECT) { if (std::abs(y - gpos.y) < minDist) { minDist = std::abs(y - gpos.y); bestY = y; closestCurve = curve; } } } if (closestCurve.get() != nullptr) { nvgBeginPath(nvg); nvgStrokeWidth(nvg, 2.0f); nvgFillColor(nvg, closestCurve->color); nvgStrokeColor(nvg, context->theme.LIGHTER); float2 pt(gpos.x, bestY); pt = (pt - graphBounds.position) / graphBounds.dimensions; pt.y = 1.0f - pt.y; pt = pt * gbounds.dimensions + gbounds.position; nvgCircle(nvg, pt.x, pt.y, 4); nvgFill(nvg); nvgStroke(nvg); nvgBeginPath(nvg); nvgFillColor(nvg, context->theme.DARK); nvgCircle(nvg, cursorPosition.x, cursorPosition.y, 2); nvgFill(nvg); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE); nvgFontSize(nvg, MEDIUM_TEXT); drawText(nvg, float2(pt.x - 8, pt.y), closestCurve->name, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); drawText(nvg, float2(pt.x + 8, pt.y), MakeString() << "(" << std::setprecision(2) << gpos.x << ", " << std::setprecision(2) << bestY << ")", FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); } else { nvgBeginPath(nvg); nvgFillColor(nvg, context->theme.DARK); nvgCircle(nvg, cursorPosition.x, cursorPosition.y, 2); nvgFill(nvg); } } }
void drawEyes(struct NVGcontext* vg, float x, float y, float w, float h, float mx, float my, float t) { struct NVGpaint gloss, bg; float ex = w *0.23f; float ey = h * 0.5f; float lx = x + ex; float ly = y + ey; float rx = x + w - ex; float ry = y + ey; float dx,dy,d; float br = (ex < ey ? ex : ey) * 0.5f; float blink = 1 - powf(sinf(t*0.5f),200)*0.8f; bg = nvgLinearGradient(vg, x,y+h*0.5f,x+w*0.1f,y+h, nvgRGBA(0,0,0,32), nvgRGBA(0,0,0,16) ); nvgBeginPath(vg); nvgEllipse(vg, lx+3.0f,ly+16.0f, ex,ey); nvgEllipse(vg, rx+3.0f,ry+16.0f, ex,ey); nvgFillPaint(vg, bg); nvgFill(vg); bg = nvgLinearGradient(vg, x,y+h*0.25f,x+w*0.1f,y+h, nvgRGBA(220,220,220,255), nvgRGBA(128,128,128,255) ); nvgBeginPath(vg); nvgEllipse(vg, lx,ly, ex,ey); nvgEllipse(vg, rx,ry, ex,ey); nvgFillPaint(vg, bg); nvgFill(vg); dx = (mx - rx) / (ex * 10); dy = (my - ry) / (ey * 10); d = sqrtf(dx*dx+dy*dy); if (d > 1.0f) { dx /= d; dy /= d; } dx *= ex*0.4f; dy *= ey*0.5f; nvgBeginPath(vg); nvgEllipse(vg, lx+dx,ly+dy+ey*0.25f*(1-blink), br,br*blink); nvgFillColor(vg, nvgRGBA(32,32,32,255) ); nvgFill(vg); dx = (mx - rx) / (ex * 10); dy = (my - ry) / (ey * 10); d = sqrtf(dx*dx+dy*dy); if (d > 1.0f) { dx /= d; dy /= d; } dx *= ex*0.4f; dy *= ey*0.5f; nvgBeginPath(vg); nvgEllipse(vg, rx+dx,ry+dy+ey*0.25f*(1-blink), br,br*blink); nvgFillColor(vg, nvgRGBA(32,32,32,255) ); nvgFill(vg); gloss = nvgRadialGradient(vg, lx-ex*0.25f,ly-ey*0.5f, ex*0.1f,ex*0.75f, nvgRGBA(255,255,255,128), nvgRGBA(255,255,255,0) ); nvgBeginPath(vg); nvgEllipse(vg, lx,ly, ex,ey); nvgFillPaint(vg, gloss); nvgFill(vg); gloss = nvgRadialGradient(vg, rx-ex*0.25f,ry-ey*0.5f, ex*0.1f,ex*0.75f, nvgRGBA(255,255,255,128), nvgRGBA(255,255,255,0) ); nvgBeginPath(vg); nvgEllipse(vg, rx,ry, ex,ey); nvgFillPaint(vg, gloss); nvgFill(vg); }
void NanoVG::fill() { nvgFill( m_context() ); }
void Slider::draw(NVGcontext* ctx) { Vector2f center = mPos.cast<float>() + mSize.cast<float>() * 0.5f; float kr = (int) (mSize.y() * 0.4f), kshadow = 3; float startX = kr + kshadow + mPos.x(); float widthX = mSize.x() - 2*(kr+kshadow); Vector2f knobPos(startX + (mValue - mRange.first) / (mRange.second - mRange.first) * widthX, center.y() + 0.5f); NVGpaint bg = nvgBoxGradient( ctx, startX, center.y() - 3 + 1, widthX, 6, 3, 3, Color(0, mEnabled ? 32 : 10), Color(0, mEnabled ? 128 : 210)); nvgBeginPath(ctx); nvgRoundedRect(ctx, startX, center.y() - 3 + 1, widthX, 6, 2); nvgFillPaint(ctx, bg); nvgFill(ctx); if (mHighlightedRange.second != mHighlightedRange.first) { nvgBeginPath(ctx); nvgRoundedRect(ctx, startX + mHighlightedRange.first * mSize.x(), center.y() - kshadow + 1, widthX * (mHighlightedRange.second - mHighlightedRange.first), kshadow * 2, 2); nvgFillColor(ctx, mHighlightColor); nvgFill(ctx); } NVGpaint knobShadow = nvgRadialGradient(ctx, knobPos.x(), knobPos.y(), kr - kshadow, kr + kshadow, Color(0, 64), mTheme->mTransparent); nvgBeginPath(ctx); nvgRect(ctx, knobPos.x() - kr - 5, knobPos.y() - kr - 5, kr * 2 + 10, kr * 2 + 10 + kshadow); nvgCircle(ctx, knobPos.x(), knobPos.y(), kr); nvgPathWinding(ctx, NVG_HOLE); nvgFillPaint(ctx, knobShadow); nvgFill(ctx); NVGpaint knob = nvgLinearGradient(ctx, mPos.x(), center.y() - kr, mPos.x(), center.y() + kr, mTheme->mBorderLight, mTheme->mBorderMedium); NVGpaint knobReverse = nvgLinearGradient(ctx, mPos.x(), center.y() - kr, mPos.x(), center.y() + kr, mTheme->mBorderMedium, mTheme->mBorderLight); nvgBeginPath(ctx); nvgCircle(ctx, knobPos.x(), knobPos.y(), kr); nvgStrokeColor(ctx, mTheme->mBorderDark); nvgFillPaint(ctx, knob); nvgStroke(ctx); nvgFill(ctx); nvgBeginPath(ctx); nvgCircle(ctx, knobPos.x(), knobPos.y(), kr/2); nvgFillColor(ctx, Color(150, mEnabled ? 255 : 100)); nvgStrokePaint(ctx, knobReverse); nvgStroke(ctx); nvgFill(ctx); }