NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll) { const struct nk_style_item *background; const struct nk_style_item *cursor; /* select correct colors/images to draw */ if (state & NK_WIDGET_STATE_ACTIVED) { background = &style->active; cursor = &style->cursor_active; } else if (state & NK_WIDGET_STATE_HOVER) { background = &style->hover; cursor = &style->cursor_hover; } else { background = &style->normal; cursor = &style->cursor_normal; } /* draw background */ if (background->type == NK_STYLE_ITEM_COLOR) { nk_fill_rect(out, *bounds, style->rounding, background->data.color); nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); } else { nk_draw_image(out, *bounds, &background->data.image, nk_white); } /* draw cursor */ if (cursor->type == NK_STYLE_ITEM_COLOR) { nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color); nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color); } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white); }
/* =============================================================== * * CUSTOM WIDGET * * ===============================================================*/ static int ui_piemenu(struct nk_context *ctx, struct nk_vec2 pos, float radius, struct nk_image *icons, int item_count) { int ret = -1; struct nk_rect total_space; struct nk_rect bounds; int active_item = 0; /* pie menu popup */ struct nk_color border = ctx->style.window.border_color; struct nk_style_item background = ctx->style.window.fixed_background; ctx->style.window.fixed_background = nk_style_item_hide(); ctx->style.window.border_color = nk_rgba(0,0,0,0); total_space = nk_window_get_content_region(ctx); ctx->style.window.spacing = nk_vec2(0,0); ctx->style.window.padding = nk_vec2(0,0); if (nk_popup_begin(ctx, NK_POPUP_STATIC, "piemenu", NK_WINDOW_NO_SCROLLBAR, nk_rect(pos.x - total_space.x - radius, pos.y - radius - total_space.y, 2*radius,2*radius))) { int i = 0; struct nk_command_buffer* out = nk_window_get_canvas(ctx); const struct nk_input *in = &ctx->input; total_space = nk_window_get_content_region(ctx); ctx->style.window.spacing = nk_vec2(4,4); ctx->style.window.padding = nk_vec2(8,8); nk_layout_row_dynamic(ctx, total_space.h, 1); nk_widget(&bounds, ctx); /* outer circle */ nk_fill_circle(out, bounds, nk_rgb(50,50,50)); { /* circle buttons */ float step = (2 * 3.141592654f) / (float)(MAX(1,item_count)); float a_min = 0; float a_max = step; struct nk_vec2 center = nk_vec2(bounds.x + bounds.w / 2.0f, bounds.y + bounds.h / 2.0f); struct nk_vec2 drag = nk_vec2(in->mouse.pos.x - center.x, in->mouse.pos.y - center.y); float angle = (float)atan2(drag.y, drag.x); if (angle < -0.0f) angle += 2.0f * 3.141592654f; active_item = (int)(angle/step); for (i = 0; i < item_count; ++i) { struct nk_rect content; float rx, ry, dx, dy, a; nk_fill_arc(out, center.x, center.y, (bounds.w/2.0f), a_min, a_max, (active_item == i) ? nk_rgb(45,100,255): nk_rgb(60,60,60)); /* separator line */ rx = bounds.w/2.0f; ry = 0; dx = rx * (float)cos(a_min) - ry * (float)sin(a_min); dy = rx * (float)sin(a_min) + ry * (float)cos(a_min); nk_stroke_line(out, center.x, center.y, center.x + dx, center.y + dy, 1.0f, nk_rgb(50,50,50)); /* button content */ a = a_min + (a_max - a_min)/2.0f; rx = bounds.w/2.5f; ry = 0; content.w = 30; content.h = 30; content.x = center.x + ((rx * (float)cos(a) - ry * (float)sin(a)) - content.w/2.0f); content.y = center.y + (rx * (float)sin(a) + ry * (float)cos(a) - content.h/2.0f); nk_draw_image(out, content, &icons[i], nk_rgb(255,255,255)); a_min = a_max; a_max += step; } } { /* inner circle */ struct nk_rect inner; inner.x = bounds.x + bounds.w/2 - bounds.w/4; inner.y = bounds.y + bounds.h/2 - bounds.h/4; inner.w = bounds.w/2; inner.h = bounds.h/2; nk_fill_circle(out, inner, nk_rgb(45,45,45)); /* active icon content */ bounds.w = inner.w / 2.0f; bounds.h = inner.h / 2.0f; bounds.x = inner.x + inner.w/2 - bounds.w/2; bounds.y = inner.y + inner.h/2 - bounds.h/2; nk_draw_image(out, bounds, &icons[active_item], nk_rgb(255,255,255)); } nk_layout_space_end(ctx); if (!nk_input_is_mouse_down(&ctx->input, NK_BUTTON_RIGHT)) { nk_popup_close(ctx); ret = active_item; } } else ret = -2; ctx->style.window.spacing = nk_vec2(4,4); ctx->style.window.padding = nk_vec2(8,8); nk_popup_end(ctx); ctx->style.window.fixed_background = background; ctx->style.window.border_color = border; return ret; }
int main(int argc, char *argv[]) { /* register callbacks */ mpx_register_vc(&this_vc); /* GUI */ static struct nk_context ctx; static struct nk_canvas canvas; uint32_t width = 0, height = 0; static struct nk_user_font font; font.userdata.ptr = &width; font.height = font_vga_8x16.height; font.width = your_text_width_calculation; nk_init_default(&ctx, &font); width = this_vc.fb->var.xres; height = this_vc.fb->var.yres; /* Draw */ while (1) { /* what to draw */ canvas_begin(&ctx, &canvas, 0, 0, 0, width, height, nk_rgb(100,100,100)); { canvas.painter->use_clipping = NK_CLIPPING_OFF; nk_fill_rect(canvas.painter, nk_rect(15,15,140,140), 5, nk_rgb(247, 230, 154)); nk_fill_rect(canvas.painter, nk_rect(20,20,135,135), 5, nk_rgb(188, 174, 118)); nk_draw_text(canvas.painter, nk_rect(30, 30, 100, 20), "Text to draw", 12, &font, nk_rgb(188,174,118), nk_rgb(0,0,0)); nk_fill_rect(canvas.painter, nk_rect(160,20,70,70), 0, nk_rgb(0,0,255)); nk_fill_circle(canvas.painter, nk_rect(20,160,60,60), nk_rgb(255,0,0)); nk_fill_triangle(canvas.painter, 160, 160, 230, 160, 195, 220, nk_rgb(0,255,0)); nk_fill_arc(canvas.painter, 195, 120, 30, 0, 3.141592654f * 3.0f / 4.0f, nk_rgb(255,255,0)); nk_stroke_line(canvas.painter, 15, 10, 100, 10, 2.0f, nk_rgb(189,45,75)); nk_stroke_rect(canvas.painter, nk_rect(235, 20, 70, 70), 10, 3, nk_rgb(0,0,255)); nk_stroke_curve(canvas.painter, 235, 130, 252, 170, 288, 80, 305, 130, 1, nk_rgb(0,150,220)); nk_stroke_triangle(canvas.painter, 235, 160, 305, 160, 270, 220, 10, nk_rgb(255,0,143)); nk_stroke_circle(canvas.painter, nk_rect(90, 160, 60, 60), 2, nk_rgb(0,255,120)); /* load some image */ // uint32_t im_w, im_h, im_format; // images[0] = stbi_load("SPBGU_logo.png", &im_w, &im_h, &im_format, 0); // if (images[0] == NULL) // printf("\nstbi_load doesn't work. :(\n"); // else { // printf("\nLoaded image: id = %i width = %i\theight = %i\tformat = %i", (int)*images[0], im_w, im_h, im_format); struct nk_image im; im.handle.ptr = "SPBGU_logo.png"; im.handle.id = 0; im.w = 0; im.h = 0; im.region[0] = 0; im.region[1] = 0; im.region[2] = 267; im.region[3] = 333; nk_draw_image(canvas.painter, nk_rect(320, 10, 130, 150), &im, nk_rgb(100, 0, 0)); // } // stbi_image_free(images[0]); } canvas_end(&ctx, &canvas); /* Draw each element */ draw(&this_vc, &ctx, width, height); } nk_free(&ctx); printf("\nEnd of program.\nIf you see it then something goes wrong.\n"); return 0; }
CharacterDialoguePopup::UpdateResult CharacterDialoguePopup::update(struct nk_context* ctx) { auto renderer = FARender::Renderer::get(); auto boxTex = renderer->loadImage(this->mWide ? "data/textbox.cel" : "data/textbox2.cel"); int32_t screenW, screenH; renderer->getWindowDimensions(screenW, screenH); nk_flags flags = NK_WINDOW_NO_SCROLLBAR; auto dialogRectangle = nk_rect(screenW / 2.0f - (boxTex->getWidth() / 2.0f), screenH / 2.0f - (boxTex->getHeight() / 2.0f), boxTex->getWidth(), boxTex->getHeight()); UpdateResult result = UpdateResult::DoNothing; mGuiManager.nk_fa_begin_image_window(ctx, "dialog", dialogRectangle, flags, boxTex->getNkImage(), [&]() { // apply black checkerboard in background { auto blackTex = renderer->loadImage("resources/black.png"); auto cbRect = nk_rect(dialogRectangle.x + 3, dialogRectangle.y + 3, dialogRectangle.w - 6, dialogRectangle.h - 6); ScopedApplyEffect effect(ctx, EffectType::checkerboarded); auto nkImage = nk_subimage_handle(blackTex->getNkImage().handle, blackTex->getWidth(), blackTex->getHeight(), cbRect); nk_draw_image(nk_window_get_canvas(ctx), cbRect, &nkImage, nk_rgb(0, 0, 0)); } nk_layout_row_dynamic(ctx, 30, 1); DialogData data = getDialogData(); for (const auto& line : data.introduction) GuiManager::smallText(ctx, line.c_str()); // fill the rest of the window struct nk_rect bounds = nk_widget_bounds(ctx); struct nk_rect panelSize = nk_window_get_bounds(ctx); float contentHeight = panelSize.h + panelSize.y - bounds.y; nk_layout_row_dynamic(ctx, contentHeight, 1); Misc::ScopedSetter<nk_style> styleSetter(ctx->style); // setup style for scrollbar { constexpr int32_t scrollUpButtonIndex = 9; constexpr int32_t scrollDownButtonIndex = 8; constexpr int32_t scrollbarBackgroundIndex = 13; // TODO: the "cursor" of the scrollbar is still the default nuklear look, which should change auto sliderImg = renderer->loadImage("data/textslid.cel"); // TODO: this image should repeat, not stretch ctx->style.scrollv.normal = nk_style_item_image(sliderImg->getNkImage(scrollbarBackgroundIndex)); ctx->style.scrollv.active = ctx->style.scrollv.normal; ctx->style.scrollv.hover = ctx->style.scrollv.normal; ctx->style.scrollv.cursor_active = ctx->style.scrollv.cursor_normal; ctx->style.scrollv.cursor_hover = ctx->style.scrollv.cursor_normal; ctx->style.scrollv.show_buttons = true; ctx->style.scrollv.dec_button.normal = nk_style_item_image(sliderImg->getNkImage(scrollUpButtonIndex)); ctx->style.scrollv.dec_symbol = NK_SYMBOL_NONE; ctx->style.scrollv.inc_button.normal = nk_style_item_image(sliderImg->getNkImage(scrollDownButtonIndex)); ctx->style.scrollv.inc_symbol = NK_SYMBOL_NONE; ctx->style.scrollv.dec_button.active = ctx->style.scrollv.dec_button.normal; ctx->style.scrollv.dec_button.hover = ctx->style.scrollv.dec_button.normal; ctx->style.scrollv.inc_button.active = ctx->style.scrollv.inc_button.normal; ctx->style.scrollv.inc_button.hover = ctx->style.scrollv.inc_button.normal; ctx->style.window.group_padding = nk_vec2(10, 10); ctx->style.window.scrollbar_size = nk_vec2(sliderImg->getWidth(), 0); } nk_group_scrolled_begin(ctx, &mScroll, "dialog_main", 0); { if (mDialogMenu.update(ctx, data.dialogOptions, mScroll) == MouseAndClickMenu::Result::Activated) result = data.dialogActions[mDialogMenu.getSelectedIndex()](); } nk_group_scrolled_end(ctx); }, true); return result; }
int main(int argc, char** argv) { if (argc > 2) message_and_abort_fmt("Usage: %s [filename]", argv[0]); Render::RenderSettings renderSettings; renderSettings.windowWidth = 800; renderSettings.windowHeight = 600; renderSettings.fullscreen = false; NuklearMisc::StandaloneGuiHandler guiHandler("Cel Viewer", renderSettings); nk_context* ctx = guiHandler.getNuklearContext(); Settings::Settings settings; settings.loadFromFile("resources/celview.ini"); bool faioInitDone = false; std::string listFile = settings.get<std::string>("celview", "listFile", "Diablo I.txt"); std::string mpqFile = settings.get<std::string>("celview", "mpqFile", "DIABDAT.MPQ"); std::vector<std::string> celFiles; std::string selectedImage = ""; std::unique_ptr<NuklearMisc::GuiSprite> image; std::unique_ptr<NuklearMisc::GuiSprite> nextImage; int animate = false; int32_t frame = 0; float rowHeight = 30; auto lastFrame = std::chrono::high_resolution_clock::now(); bool quit = false; while (!quit) { auto now = std::chrono::high_resolution_clock::now(); if (nextImage) image = std::unique_ptr<NuklearMisc::GuiSprite>(nextImage.release()); renderSettings = Render::getWindowSize(); if (nk_begin(ctx, "main_window", nk_rect(0, 0, renderSettings.windowWidth, renderSettings.windowHeight), NK_WINDOW_NO_SCROLLBAR)) { struct nk_rect bounds = nk_window_get_content_region(ctx); nk_layout_row_dynamic(ctx, bounds.h, 2); if (nk_group_begin(ctx, "image", 0)) { nk_layout_row_dynamic(ctx, rowHeight, 1); std::string label = selectedImage; if (selectedImage == "") label = "No image selected"; nk_label(ctx, label.c_str(), NK_TEXT_CENTERED); nk_checkbox_label(ctx, "Animate", &animate); if (image) { nk_label(ctx, (boost::format("Number of Frames: %1%") % image.get()->getSprite()->size()).str().c_str(), NK_TEXT_LEFT); nk_label(ctx, (boost::format("Width: %1%") % image->getSprite()->getWidth()).str().c_str(), NK_TEXT_LEFT); nk_label(ctx, (boost::format("Height: %1%") % image->getSprite()->getHeight()).str().c_str(), NK_TEXT_LEFT); frame = nk_propertyi(ctx, "Frame", 0, frame, image->getSprite()->size(), 1, 0.2f); if (nk_button_label(ctx, "save as png")) { nfdchar_t* outPath = NULL; nfdresult_t result = NFD_SaveDialog("png", NULL, &outPath); if (result == NFD_OKAY) { Render::SpriteGroup::toPng(selectedImage, outPath); free(outPath); } } if (nk_button_label(ctx, "save as gif")) { nfdchar_t* outPath = NULL; nfdresult_t result = NFD_SaveDialog("gif", NULL, &outPath); if (result == NFD_OKAY) { Render::SpriteGroup::toGif(selectedImage, outPath); free(outPath); } } auto msSinceLastFrame = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastFrame).count(); if (animate && msSinceLastFrame > 100) { lastFrame = now; frame++; } if (frame >= (int32_t)image.get()->getSprite()->size()) frame = 0; Render::Sprite sprite = image.get()->getSprite()->operator[](frame); int32_t w, h; Render::spriteSize(sprite, w, h); nk_layout_space_begin(ctx, NK_STATIC, h, 1); { nk_layout_space_push(ctx, nk_rect(0, 0, w, h)); auto canvas = nk_window_get_canvas(ctx); struct nk_rect imageRect; nk_widget(&imageRect, ctx); nk_fill_rect(canvas, imageRect, 0.0, nk_rgb(0, 255, 0)); auto img = image.get()->getNkImage(frame); nk_draw_image(canvas, imageRect, &img, nk_rgb(255, 255, 255)); } nk_layout_space_end(ctx); } nk_group_end(ctx); } if (nk_group_begin(ctx, "file list", 0)) { if (!faioInitDone) { nk_layout_row_dynamic(ctx, rowHeight * 2, 1); NuklearMisc::nk_file_pick(ctx, "DIABDAT.MPQ", mpqFile, "mpq,MPQ", rowHeight); NuklearMisc::nk_file_pick(ctx, "Diablo listfile", listFile, "txt", rowHeight); if (nk_button_label(ctx, "load")) { FAIO::init(mpqFile, listFile); celFiles = FAIO::listMpqFiles("*.cel"); auto tmp = FAIO::listMpqFiles("*.cl2"); celFiles.insert(celFiles.end(), tmp.begin(), tmp.end()); std::sort(celFiles.begin(), celFiles.end()); settings.set<std::string>("celview", "listFile", listFile); settings.set<std::string>("celview", "mpqFile", mpqFile); settings.save(); faioInitDone = true; if (argc > 1) { selectedImage = argv[1]; frame = 0; nextImage = std::unique_ptr<NuklearMisc::GuiSprite>(guiHandler.getSprite(new Render::SpriteGroup(selectedImage))); } } } nk_layout_row_dynamic(ctx, rowHeight, 1); for (size_t i = 0; i < celFiles.size(); i++) { auto buttonStyle = ctx->style.button; if (selectedImage == celFiles[i]) buttonStyle.normal = buttonStyle.hover; if (nk_button_label_styled(ctx, &buttonStyle, celFiles[i].c_str())) { selectedImage = celFiles[i]; frame = 0; nextImage = std::unique_ptr<NuklearMisc::GuiSprite>(guiHandler.getSprite(new Render::SpriteGroup(selectedImage))); } } nk_group_end(ctx); } } nk_end(ctx); quit = guiHandler.update(); } FAIO::quit(); return 0; }
NK_API int nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len, struct nk_image img, struct nk_vec2 size) { struct nk_window *win; struct nk_style *style; struct nk_input *in; struct nk_rect header; int is_clicked = nk_false; enum nk_widget_layout_states s; const struct nk_style_item *background; struct nk_text text; NK_ASSERT(ctx); NK_ASSERT(ctx->current); NK_ASSERT(ctx->current->layout); if (!ctx || !ctx->current || !ctx->current->layout) return 0; win = ctx->current; style = &ctx->style; s = nk_widget(&header, ctx); if (!s) return 0; in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) is_clicked = nk_true; /* draw combo box header background and border */ if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { background = &style->combo.active; text.text = style->combo.label_active; } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { background = &style->combo.hover; text.text = style->combo.label_hover; } else { background = &style->combo.normal; text.text = style->combo.label_normal; } if (background->type == NK_STYLE_ITEM_IMAGE) { text.background = nk_rgba(0,0,0,0); nk_draw_image(&win->buffer, header, &background->data.image, nk_white); } else { text.background = background->data.color; nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); } { struct nk_rect content; struct nk_rect button; struct nk_rect label; struct nk_rect image; enum nk_symbol_type sym; if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) sym = style->combo.sym_hover; else if (is_clicked) sym = style->combo.sym_active; else sym = style->combo.sym_normal; /* calculate button */ button.w = header.h - 2 * style->combo.button_padding.y; button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; button.y = header.y + style->combo.button_padding.y; button.h = button.w; content.x = button.x + style->combo.button.padding.x; content.y = button.y + style->combo.button.padding.y; content.w = button.w - 2 * style->combo.button.padding.x; content.h = button.h - 2 * style->combo.button.padding.y; nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, &ctx->style.combo.button, sym, style->font); /* draw image */ image.x = header.x + style->combo.content_padding.x; image.y = header.y + style->combo.content_padding.y; image.h = header.h - 2 * style->combo.content_padding.y; image.w = image.h; nk_draw_image(&win->buffer, image, &img, nk_white); /* draw label */ text.padding = nk_vec2(0,0); label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; label.y = header.y + style->combo.content_padding.y; label.w = (button.x - style->combo.content_padding.x) - label.x; label.h = header.h - 2 * style->combo.content_padding.y; nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); } return nk_combo_begin(ctx, win, size, is_clicked, header); }
NK_API int nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size) { struct nk_window *win; struct nk_style *style; const struct nk_input *in; struct nk_rect header; int is_clicked = nk_false; enum nk_widget_layout_states s; const struct nk_style_item *background; NK_ASSERT(ctx); NK_ASSERT(ctx->current); NK_ASSERT(ctx->current->layout); if (!ctx || !ctx->current || !ctx->current->layout) return 0; win = ctx->current; style = &ctx->style; s = nk_widget(&header, ctx); if (s == NK_WIDGET_INVALID) return 0; in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) is_clicked = nk_true; /* draw combo box header background and border */ if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) background = &style->combo.active; else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) background = &style->combo.hover; else background = &style->combo.normal; if (background->type == NK_STYLE_ITEM_IMAGE) { nk_draw_image(&win->buffer, header, &background->data.image, nk_white); } else { nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); } { struct nk_rect bounds = {0,0,0,0}; struct nk_rect content; struct nk_rect button; enum nk_symbol_type sym; if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) sym = style->combo.sym_hover; else if (is_clicked) sym = style->combo.sym_active; else sym = style->combo.sym_normal; /* calculate button */ button.w = header.h - 2 * style->combo.button_padding.y; button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; button.y = header.y + style->combo.button_padding.y; button.h = button.w; content.x = button.x + style->combo.button.padding.x; content.y = button.y + style->combo.button.padding.y; content.w = button.w - 2 * style->combo.button.padding.x; content.h = button.h - 2 * style->combo.button.padding.y; /* draw image */ bounds.h = header.h - 2 * style->combo.content_padding.y; bounds.y = header.y + style->combo.content_padding.y; bounds.x = header.x + style->combo.content_padding.x; bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; nk_draw_image(&win->buffer, bounds, &img, nk_white); /* draw open/close button */ nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, &ctx->style.combo.button, sym, style->font); } return nk_combo_begin(ctx, win, size, is_clicked, header); }