void CheckerboardGlyph::draw(const box2px& bounds, const Color& fgColor, const Color& bgColor, AlloyContext* context) { NVGcontext* nvg = context->nvgContext; NVGpaint imgPaint = nvgImagePattern(nvg, bounds.position.x, bounds.position.y, bounds.dimensions.x, bounds.dimensions.y, 0.f, handle, 1.0f); if (bgColor.a > 0) { nvgBeginPath(nvg); nvgRect(nvg, bounds.position.x, bounds.position.y, bounds.dimensions.x, bounds.dimensions.y); nvgFillColor(nvg, Color(bgColor)); nvgFill(nvg); } nvgBeginPath(nvg); nvgRect(nvg, bounds.position.x, bounds.position.y, bounds.dimensions.x, bounds.dimensions.y); nvgFillPaint(nvg, imgPaint); nvgFill(nvg); if (fgColor.a > 0) { nvgBeginPath(nvg); nvgRect(nvg, bounds.position.x, bounds.position.y, bounds.dimensions.x, bounds.dimensions.y); nvgFillColor(nvg, Color(fgColor)); nvgFill(nvg); } }
virtual void updateGL( osg::State* state ) const { // Some test drawings... nvgBeginPath( _vg ); nvgRect( _vg, 300, 300, 120, 30 ); nvgFillColor( _vg, nvgRGBA(255, 192, 0, 255) ); nvgFill( _vg ); nvgClosePath( _vg ); nvgBeginPath( _vg ); nvgCircle( _vg, 400, 500, 50 ); nvgFillColor( _vg, nvgRGBA(0, 192, 255, 100) ); nvgFill( _vg ); nvgClosePath( _vg ); if ( _loadedImages.size()>0 ) { NVGpaint imgPaint = nvgImagePattern( _vg, 600, 150, 300, 400, 0.0f, _loadedImages[0], 1.0f ); nvgBeginPath( _vg ); nvgRoundedRect( _vg, 600, 150, 300, 400, 5 ); nvgFillPaint( _vg, imgPaint ); nvgFill( _vg ); nvgClosePath( _vg ); } }
void Renderer2D::drawRectangle( const attributes_2d& attributes, const float32_t& width, const float32_t& height, const float32_t& border, const color_argb& color, const color_argb& borderColor, const Image2D& image, const float32_t& image_alpha, const float32_t& image_pos_x, const float32_t& image_pos_y, const float32_t& image_width, const float32_t& image_height, const float32_t& image_rotation ) { Context2D* context = _context2D; const float32_t sWidth = width * attributes.scale; const float32_t sHeight = height * attributes.scale; nvgSave( context ); nvgBeginPath( context ); nvgTranslate( context, attributes.position[0], attributes.position[1] ); nvgSave( context ); nvgRotate( context, attributes.rotation ); nvgRect( context, -sWidth/2, -sHeight/2, sWidth, sHeight ); if( image != 0 ) { NVGpaint paint = nvgImagePattern( context, (-sWidth/2)+image_pos_x, (-sHeight/2)+image_pos_y, image_width, image_height, image_rotation, image, image_alpha ); nvgFillPaint( context, paint); } else { nvgFillColor( context, nvgRGBA( color.r, color.g, color.b, color.a) ); } nvgFill( context ); nvgStrokeColor( context, nvgRGBA( borderColor.r, borderColor.g, borderColor.b, borderColor.a) ); nvgStrokeWidth( context, border ); nvgStroke( context ); nvgRestore( context ); nvgRestore( context ); }
void QNanoPainter::drawImage(QNanoImage &image, const QRectF sourceRect, const QRectF destinationRect) { image.setParentPainter(this); float sx = sourceRect.x(); float sy = sourceRect.y(); float sw = sourceRect.width(); float sh = sourceRect.height(); float dx = destinationRect.x(); float dy = destinationRect.y(); float dw = destinationRect.width(); float dh = destinationRect.height(); _checkAlignPixelsAdjust(&dx, &dy); _checkAlignPixels(&dw, &dh); float startX = dx - sx * (dw/sw); float startY = dy - sy * (dh/sh); float endX = dw * image.width() / sw; float endY = dh * image.height() / sh; NVGpaint ip = nvgImagePattern(nvgCtx(), startX, startY, endX, endY, 0.0f, image.getID(nvgCtx()), 1.0f); nvgSave(nvgCtx()); nvgBeginPath(nvgCtx()); rect(dx, dy, dw, dh); nvgFillPaint(nvgCtx(), ip); nvgFill(nvgCtx()); nvgRestore(nvgCtx()); }
void Renderer2D::drawCircle( const attributes_2d& attributes, const float32_t& radius, const float32_t& border, const color_argb& color, const color_argb& borderColor, const Image2D& image, const float32_t& image_alpha, const float32_t& image_pos_x, const float32_t& image_pos_y, const float32_t& image_width, const float32_t& image_height, const float32_t& image_rotation ) { Context2D* context = _context2D; nvgSave( context ); nvgBeginPath( context ); nvgTranslate( context, attributes.position[0], attributes.position[1]); nvgSave( context ); nvgRotate( context, attributes.rotation ); nvgCircle( context, 0, 0, radius * attributes.scale ); if( image != 0 ) { NVGpaint paint = nvgImagePattern( context, image_pos_x-image_width/2, image_pos_y - image_height/2, image_width, image_height, image_rotation, image, image_alpha ); nvgFillPaint( context, paint); } else { nvgFillColor( context, nvgRGBA( color.r, color.g, color.b, color.a) ); } nvgFill(context); nvgStrokeColor( context, nvgRGBA( borderColor.r, borderColor.g, borderColor.b, borderColor.a) ); nvgStrokeWidth( context, border ); nvgStroke( context ); nvgRestore( context ); nvgRestore( context ); }
void NanoInk::drawImage(int image, float left, float top, float width, float height, float imgx, float imgy, float imgw, float imgh) { NVGpaint imgPaint = nvgImagePattern(mCtx, imgx, imgy, imgw, imgh, 0.0f / 180.0f*NVG_PI, image, 1.f); nvgBeginPath(mCtx); nvgRect(mCtx, left, top, width, height); nvgFillPaint(mCtx, imgPaint); nvgFill(mCtx); }
JNIEXPORT void JNICALL Java_firststep_internal_NVG__1_1imagePattern (JNIEnv *e, jclass c, jlong ctx, jobject paint, jfloat ox, jfloat oy, jfloat ex, jfloat ey, jfloat angle, jint image, jfloat alpha) { // paint can't be null as it's passed internally as the objects instance as a convenience NVGpaint p = nvgImagePattern((NVGcontext*)ctx, ox, oy, ex, ey, angle, image, alpha); NVGpaint* dp = getBuffPtr(e,paint); *dp = p; }
static void draw_image(NVGcontext *ctx, gui_handle img, float x, float y, float w, float h, float r) { NVGpaint imgpaint; imgpaint = nvgImagePattern(ctx, x, y, w, h, 0, img.id, 1.0f); nvgBeginPath(ctx); nvgRoundedRect(ctx, x, y, w, h, r); nvgFillPaint(ctx, imgpaint); nvgFill(ctx); }
void QNanoPainter::drawImage(QNanoImage &image, float x, float y, float width, float height) { _checkAlignPixelsAdjust(&x, &y); _checkAlignPixels(&width, &height); image.setParentPainter(this); NVGpaint ip = nvgImagePattern(nvgCtx(), x, y, width, height, 0.0f, image.getID(nvgCtx()), 1.0f); nvgSave(nvgCtx()); nvgBeginPath(nvgCtx()); nvgRect(nvgCtx(), x, y, width, height); nvgFillPaint(nvgCtx(), ip); nvgFill(nvgCtx()); nvgRestore(nvgCtx()); }
void ImagePanel::draw (NVGcontext * ctx) { ivec2 grid = gridSize(); for (size_t i = 0; i < mImages.size(); ++i) { ivec2 p = mPos + ivec2 (mMargin) + ivec2 ((int)i % grid.x, (int)i / grid.x) * (mThumbSize + mSpacing); int imgw, imgh; nvgImageSize (ctx, mImages[i].first, &imgw, &imgh); float iw, ih, ix, iy; if (imgw < imgh) { iw = mThumbSize; ih = iw * (float)imgh / (float)imgw; ix = 0; iy = - (ih - mThumbSize) * 0.5f; } else { ih = mThumbSize; iw = ih * (float)imgw / (float)imgh; ix = - (iw - mThumbSize) * 0.5f; iy = 0; } NVGpaint imgPaint = nvgImagePattern ( ctx, p.x + ix, p.y + iy, iw, ih, 0, mImages[i].first, mMouseIndex == (int)i ? 1.0 : 0.7); nvgBeginPath (ctx); nvgRoundedRect (ctx, p.x, p.y, mThumbSize, mThumbSize, 5); nvgFillPaint (ctx, imgPaint); nvgFill (ctx); NVGpaint shadowPaint = nvgBoxGradient (ctx, p.x - 1, p.y, mThumbSize + 2, mThumbSize + 2, 5, 3, nvgRGBA (0, 0, 0, 128), nvgRGBA (0, 0, 0, 0)); nvgBeginPath (ctx); nvgRect (ctx, p.x - 5, p.y - 5, mThumbSize + 10, mThumbSize + 10); nvgRoundedRect (ctx, p.x, p.y, mThumbSize, mThumbSize, 6); nvgPathWinding (ctx, NVG_HOLE); nvgFillPaint (ctx, shadowPaint); nvgFill (ctx); nvgBeginPath (ctx); nvgRoundedRect (ctx, p.x + 0.5f, p.y + 0.5f, mThumbSize - 1, mThumbSize - 1, 4 - 0.5f); nvgStrokeWidth (ctx, 1.0f); nvgStrokeColor (ctx, nvgRGBA (255, 255, 255, 80)); nvgStroke (ctx); } }
void t2Image::drawInCircle(int x, int y, float radius, int angle /*= 0*/, int alpha /*= 255*/, bool bFill /*= true*/) { NVGpaint imgPaint = nvgImagePattern(t2GetContext(), x, y, width, height, angle / 255.0f, img, alpha / 255.0f); nvgBeginPath(t2GetContext()); nvgCircle(t2GetContext(), x, y, radius); if(bFill) { nvgFillPaint(t2GetContext(), imgPaint); nvgFill(t2GetContext()); } else { nvgStrokePaint(t2GetContext(), imgPaint); nvgStroke(t2GetContext()); } }
void background(BATB& batb, run::World& run) { auto* nvg = batb.gl.nanovg_begin( run.scene ); auto wth = run.scene.wth; auto hth = run.scene.hth; //nvgTranslate( nvg, wth / 2, hth / 2 ); float_t x = 0.5 * (wth - image_wth); float_t y = 0.5 * (hth - image_hth); image_paint = nvgImagePattern( nvg, x, y, image_wth, image_hth, 0.0, image, 1.0 ); nvgBeginPath( nvg ); //nvgRect( nvg, x, y, image_wth, image_hth ); nvgRect( nvg, x, y, wth, hth ); nvgFillPaint( nvg, image_paint ); nvgFill( nvg ); batb.gl.nanovg_end(); }
void Renderer2D::drawPath( const attributes_2d& attributes, const float32_t* path, const uint32_t& pathSize, const float32_t& border, const color_argb& color, const color_argb& borderColor, const Image2D& image, const float32_t& image_alpha, const float32_t& image_pos_x, const float32_t& image_pos_y, const float32_t& image_width, const float32_t& image_height, const float32_t& image_rotation ) { Context2D* context = _context2D; if( pathSize < 2 || pathSize % 2 != 0 ) return; nvgSave( context ); nvgBeginPath( context ); nvgTranslate( context, attributes.position[0], attributes.position[1] ); nvgSave( context ); nvgRotate( context, attributes.rotation ); nvgMoveTo( context, path[0], path[1]); for( uint32_t i=2; i<pathSize; i+=2 ) { nvgLineTo( context, path[i] * attributes.scale, path[i+1] * attributes.scale); } nvgClosePath( context ); if( image != 0 ) { NVGpaint paint = nvgImagePattern( context, image_pos_x-image_width/2, image_pos_y-image_height/2, image_width, image_height, image_rotation, image, image_alpha ); nvgFillPaint( context, paint); } else { nvgFillColor( context, nvgRGBA( color.r, color.g, color.b, color.a) ); } nvgFill(context); nvgStrokeColor( context, nvgRGBA( borderColor.r, borderColor.g, borderColor.b, borderColor.a) ); nvgStrokeWidth( context, border ); nvgStroke( context ); nvgRestore( context ); nvgRestore( context ); }
//Render a rectangle bool renderRect(Skin::SkinClass::Attributes &skinClass, float x, float y, float sw, float sh) { if (!m_inited) return false; NVGcolor col = nvgRGBA(skinClass.fill.r, skinClass.fill.g, skinClass.fill.b, skinClass.fill.a); //NVGpaint bg = nvgLinearGradient(m_vg, pos.x, pos.y, pos.x, pos.y + size.y, nvgRGBA(255,255,255,isBlack(col)?16:64), nvgRGBA(0,0,0,isBlack(col)?16:64)); nvgBeginPath(m_vg); nvgRoundedRect(m_vg, x, y, sw, sh, skinClass.cornerRadius); if (!skinClass.hasImage || skinClass.hasFill) { nvgFillColor(m_vg, col); nvgFill(m_vg); } if (skinClass.hasImage) { //int w = size.x, h= size.y; //nvgImageSize(m_vg, skinClass.imageHandle, &w, &h); NVGpaint img = nvgImagePattern(m_vg, x, y, sw, sh, 0.f, skinClass.imageHandle, col.a); nvgFillPaint(m_vg, img); nvgFill(m_vg); } if (skinClass.hasGradient) { NVGpaint g = nvgLinearGradient(m_vg, x, y, x, y + sh, nvgRGBA(skinClass.gradientA.r, skinClass.gradientA.g, skinClass.gradientA.b, skinClass.gradientA.a), nvgRGBA(skinClass.gradientB.r, skinClass.gradientB.g, skinClass.gradientB.b, skinClass.gradientB.a) ); nvgFillPaint(m_vg, g); nvgFill(m_vg); } if (skinClass.hasStroke) { nvgStrokeWidth(m_vg, skinClass.strokeWidth); nvgStrokeColor(m_vg, nvgRGBA(skinClass.stroke.r, skinClass.stroke.g, skinClass.stroke.b, skinClass.stroke.a)); nvgStroke(m_vg); } return true; }
void VectorRenderer::fillTexture(TextureID id, Loom2D::Matrix transform, bool repeat, bool smooth, float alpha) { TextureInfo *tinfo = Texture::getTextureInfo(id); // Setup flags int flags = NVG_IMAGE_NODELETE; if (tinfo->mipmaps) flags |= NVG_IMAGE_GENERATE_MIPMAPS; if (repeat) { flags |= NVG_IMAGE_REPEATX; flags |= NVG_IMAGE_REPEATY; } if (smooth) flags |= NVG_IMAGE_BILINEAR; // Key based on id and flags utIntHashKey key = utIntHashKey(utIntHashKey(id).hash() ^ utIntHashKey(flags).hash()); int *stored = imageLookup.get(key); int nvgImage; if (stored == NULL) { nvgImage = nvglCreateImageFromHandle(nvg, tinfo->getHandleID(), tinfo->width, tinfo->height, flags); imageLookup.insert(key, nvgImage); } else { nvgImage = *stored; } // Save transform float xform[6]; nvgCurrentTransform(nvg, xform); // Apply fill transform nvgTransform(nvg, (float)transform.a, (float)transform.b, (float)transform.c, (float)transform.d, (float)transform.tx, (float)transform.ty); // Set paint nvgFillPaint(nvg, nvgImagePattern(nvg, 0.f, 0.f, (float) tinfo->width, (float) tinfo->height, 0.f, nvgImage, alpha)); // Restore transform nvgSetTransform(nvg, xform); }
void ImageNode::renderItself(RenderContext& renderContext) { NVGcontext& nanoVgContext = renderContext.getNanoVgContext(); NVGpaint paint = nvgImagePattern(&nanoVgContext, mImagePatternRect.getX(), mImagePatternRect.getY(), mImagePatternRect.getWidth(), mImagePatternRect.getHeight(), 0, mImage.getHandle(), 1); nvgBeginPath(&nanoVgContext); nvgRect(&nanoVgContext, mRect.getX(), mRect.getY(), mRect.getWidth(), mRect.getHeight()); nvgFillPaint(&nanoVgContext, paint); nvgFill(&nanoVgContext); if(! renderContext.getBlendColors().empty()) { std::pair<Color, float> blendResult = renderContext.getBlendResult(); const Color& blendColor = blendResult.first; nvgBeginPath(&nanoVgContext); nvgRect(&nanoVgContext, mRect.getX(), mRect.getY(), mRect.getWidth(), mRect.getHeight()); nvgFillColor(&nanoVgContext, nvgRGBAf(blendColor.getRed(), blendColor.getGreen(), blendColor.getBlue(), blendColor.getAlpha() * blendResult.second)); nvgFill(&nanoVgContext); } Node::renderItself(renderContext); }
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 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); }
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 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 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 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); }