Nuklearã¯ãå³æã¢ãŒãã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãäœæããããã®ã©ã€ãã©ãªã§ãã ã©ã€ãã©ãªã«ã¯äŸåé¢ä¿ã¯ãããŸããïŒC89ã®ã¿ïŒããŒãã³ã¢ã®ã¿ïŒïŒãããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ãŠã£ã³ããŠã®äœææ¹æ³ãå®éã®ã¬ã³ããªã³ã°ã®å®è¡æ¹æ³ãããããŸããã Nuklearã¯ãå®è£ ãããã¢ããªã±ãŒã·ã§ã³ã䜿çšããŠã¬ã³ããªã³ã°ããããã®äŸ¿å©ãªã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããåã蟌ã¿å¯èœãªã©ã€ãã©ãªã§ãã WinAPIãX11ãSDLãAllegroãGLFWãOpenGLãDirectXã®äŸããããŸãã ã³ã³ã»ããã®èŠªã¯ImGUIã©ã€ãã©ãªã§ããã
Nuklearã¯ãªãçŸããã®ã§ããïŒ å°ãããµã€ãºïŒçŽ15,000è¡ã®ã³ãŒãïŒã§ã1ã€ã®ããããŒãã¡ã€ã«ã«å®å šã«å«ãŸããŠããã移æ€æ§ãšäœ¿ãããããéèŠããŠäœæãããŸããã ãããªãã¯ãã¡ã€ã³ã©ã€ã»ã³ã¹ã
åé¡ã®å£°æ
ç§ã¯ãã°ãã°ãæ°çŸè¡ã®ã³ãŒãã§å°ããªãŠãŒãã£ãªãã£ãäœæããªããã°ãªããªãå®è£ ã®ããã®ã¿ã¹ã¯ãæã£ãŠããŸãã éåžžãçµæã¯ä»ã®èª°ãå®éã«äœ¿çšã§ããªãã³ã³ãœãŒã«ã¢ããªã±ãŒã·ã§ã³ã§ãã ãããããã·ã³ãã«ãªGUIã§ãããã®ãŠãŒãã£ãªãã£ããã䟿å©ã«ã§ããã§ããããïŒ
ãããã£ãŠãçµæã®èŠä»¶ïŒ
- æ°çŸãããã€ããŸã§ã®å°ãããµã€ãºã
- ã¯ãã¹ãã©ãããã©ãŒã ãå°ãªããšãWindowsãšLinuxã
- Windowsã®å€éšã©ã€ãã©ãªã«äŸåããªãããããã¹ãŠã1ã€ã®EXEãã¡ã€ã«ã«å«ãŸããŠããå¿ èŠããããŸãã
- ãŸãšããª/çŸããå€èŠ³ã
- JPGããã³PNG圢åŒã®ç»åã®ãµããŒãã
- éçºã®å®¹æããWindowsããã³Linuxã§ã®éçºèœåã
Nuklearã¯ãããè¡ããŸããïŒ
ããšãã°ãdxBin2hãŠãŒãã£ãªãã£ïŒ GitHub ïŒã®äœæãæ€èšããŠãã ãã-ãã¡ã€ã«ããã€ãåäœã§èªã¿åããCé åã®åœ¢åŒã§æžã蟌ã¿ãŸãã äž»ãªæ©èœã«å ããŠãããã°ã©ã ã«ã¯ãäžèŠãªæåã®åé€ãªã©ãããããçš®é¡ã®ãã°ããºãããããŸãã éåžžããµãŒãããŒãã£ã®æ©èœã®ããã«ãç¬èªã®å°ããªãŠãŒãã£ãªãã£ãäœæãããŸãã ããšãã°ãdxBin2hã¯ã Winter Novelçšã«äœæãããASCIIãã¡ã€ã«ãååŠçããŸãã
éçºã®ãããããã¯ãã¹ãã©ãããã©ãŒã
ãŸããäœã§ããããŠåé¡ã®éçºã®åçŽãã§ã¯ãããŸããã çµå±ã®ãšãããããã«ç®ãåãããšãã©ã€ãã©ãªãäœæãããŸããããïŒ GitHubã®Readmeã«äŸããããŸã ã 絶察ã«æ確ã§ç°¡æœãª20è¡ã®ã³ãŒãã¯ãçŸããæ確ãªçµæããããããŸãã
/* init gui state */ struct nk_context ctx; nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font); enum {EASY, HARD}; int op = EASY; float value = 0.6f; int i = 20; if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220), NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) { /* fixed widget pixel width */ nk_layout_row_static(&ctx, 30, 80, 1); if (nk_button_label(&ctx, "button")) { /* event handling */ } /* fixed widget window ratio width */ nk_layout_row_dynamic(&ctx, 30, 2); if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY; if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD; /* custom widget pixel width */ nk_layout_row_begin(&ctx, NK_STATIC, 30, 2); { nk_layout_row_push(&ctx, 50); nk_label(&ctx, "Volume:", NK_TEXT_LEFT); nk_layout_row_push(&ctx, 110); nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f); } nk_layout_row_end(&ctx); } nk_end(&ctx);
ããããããã»ã©åçŽã§ã¯ãããŸããã GUIã®ã¬ã³ããªã³ã°ã«çŽæ¥é¢äžããéšåã¯æ¬åœã«ç°¡åã§ãã ã¬ã³ããŒãããã¯ãã§ãã ãã¢ãã©ã«ããŒã«ç§»åãã奜ããªãã®ãéžæããŸãã ãããŠã20è¡ããã¯çšé ãã ããã ãã§ãªããäŸã¯ç»é¢äžã§ã»ãŒåãçµæãæç»ããŸãããã¬ã³ããªã³ã°ã®ããã«ã³ãŒãã¯æ£ç¢ºã«å€§ããç°ãªããŸãã
WinAPIïŒ
static LRESULT CALLBACK WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; } if (nk_gdip_handle_event(wnd, msg, wparam, lparam)) return 0; return DefWindowProcW(wnd, msg, wparam, lparam); } int main(void) { GdipFont* font; struct nk_context *ctx; WNDCLASSW wc; RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; DWORD style = WS_OVERLAPPEDWINDOW; DWORD exstyle = WS_EX_APPWINDOW; HWND wnd; int running = 1; int needs_refresh = 1; /* Win32 */ memset(&wc, 0, sizeof(wc)); wc.lpfnWndProc = WindowProc; wc.hInstance = GetModuleHandleW(0); wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = L"NuklearWindowClass"; RegisterClassW(&wc); AdjustWindowRectEx(&rect, style, FALSE, exstyle); wnd = CreateWindowExW(exstyle, wc.lpszClassName, L"Nuklear Demo", style | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, wc.hInstance, NULL);
SDLïŒ
int main(int argc, char* argv[]) { /* Platform */ SDL_Window *win; SDL_GLContext glContext; struct nk_color background; int win_width, win_height; int running = 1; /* GUI */ struct nk_context *ctx; /* SDL setup */ SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0"); SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); win = SDL_CreateWindow("Demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI); glContext = SDL_GL_CreateContext(win); SDL_GetWindowSize(win, &win_width, &win_height);
Windowsãžã®äŸåãªã
ããŠãOpenGLã§SDL2ã¬ã³ãã©ãŒã䜿çšããŠãWindowsãLinuxãMac OS XãAndroidãiOSãªã©ã®ã¢ããªã±ãŒã·ã§ã³ãäœæããŠãã ããïŒ ãã¹ãŠãã¹ãŒããŒã§ãããæšæºã®Windowsããã±ãŒãžã«ã¯SDLã©ã€ãã©ãªã¯ãããŸããã ã ãããããªãã¯äžç·ã«ãã©ãã°ããå¿ èŠããããŸãã ãããŠãããã¯æåã®èŠä»¶ïŒå°ããªãµã€ãºïŒã«éåããŠããŸãã SDLèªäœã®ééã¯çŽ1ã¡ã¬ãã€ãã§ãã
ããããäŸã®ãªã¹ãã«ã¯GDI +ããããŸããããã¯XP以éã®Windowsã«ãããŸãã GDI +ã¯ttfãã©ã³ããPNGããã³JPGã€ã¡ãŒãžãå®è¡ã§ãããããã¯ãã¹ãŠã¡ã¢ãªããçŽæ¥ããŒãã§ããŸãã æçµçã«2ã€ã®ã¬ã³ããªã³ã°ãå¯èœã«ãªããŸããWindowsã®å Žåã¯GDI +ããã®ä»ã®å Žåã¯ãã¹ãŠSDLã§ãã ã¬ã³ããªã³ã°ã«å¿ããŠã³ãŒãã®äžéšãå¥ã®Cãã¡ã€ã«ïŒ nuklear_cross.c ïŒã«ç§»åã§ããŸãã ããããã°ãã¡ã€ã³ã³ãŒãã¯ãªãŒããŒããŒãããããã€ã³ã¿ãŒãã§ã€ã¹ã«éäžã§ããããã«ãªããéçºãå€§å¹ ã«ç°¡çŽ åãããŸãã è¿œå ã®ãã©ã¹ã¯ã³ã³ãã€ã«ã®é«éåã§ã-Nuklearå šäœãåå¥ã®ãªããžã§ã¯ããã¡ã€ã«ã«ã³ã³ãã€ã«ãããã»ãšãã©å€æŽãããŸããã
GDI +ãArial 12ptãã©ã³ããä»ããWindowsã¬ã³ããªã³ã°ïŒ
LinuxãSDL2ããã³OpenGLã«ããã¬ã³ããªã³ã°ãããã©ã«ãã®ãã©ã³ãïŒ
ã¢ããªã±ãŒã·ã§ã³ã¯éåžžã«ç°ãªã£ãŠèŠããŸãïŒ ãããŠãæåã«ç®ãåŒãã®ã¯ãã©ã³ãã§ãã
ãã©ã³ã
ãã¹ãŠã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã§ã¢ããªã±ãŒã·ã§ã³ãåãããã«è¡šç€ºããã«ã¯ãåããã©ã³ãã䜿çšããå¿ èŠããããŸãã ã©ããã«ããããšãä¿èšŒãããŠããã·ã¹ãã ãã©ã³ãã䜿çšã§ããŸãã ãããããã®ãããªãã©ã³ãã¯ãããŸããã ãããã£ãŠãã¢ããªã±ãŒã·ã§ã³ã«ãã©ã³ããå«ããå¿ èŠããããŸãã ttfãã©ã³ãã®ééã¯éåžžæ°çŸãããã€ãã§ãããå¿ èŠãªæåãå«ããµãã»ããã¯ãããããããŸãäœæãããŸãã ããšãã°ã FontSquirrel WebãµãŒãã¹ã䜿çšããŸã ã DejaVu Serifã¯40kbã«çž®å°ããŸããããããªã«æåãããŒã©ã³ãèªãããã³å€æ°ã®èšèªãå«ãŸããŠããŸãã
ãã¹ãŠåé¡ãããŸããããNuklearã®GDI +ãã©ã€ããŒã¯ããã¡ã€ã«ããã®ã¿ãã©ã³ããã¡ã¢ãªããããŒãã§ããŸããã§ããã ä¿®æ£ããå¿ èŠããããŸãã ...ãšããã§ãåãdxBin2hã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ã«ãã©ã³ããå«ããããšãã§ããŸãã
Windows DejaVuã»ãªãïŒ
LinuxãDejaVu SerifïŒ
ãã§ã«ã¯ããã«åªããŠããŸãã ããããç§ã¯ãã§ãã¯ããã¯ã¹ã®å€èŠ³ã奜ãã§ã¯ãããŸããã ãããŠãåçãèŠããã§ãã
ç»åïŒPNGãJPG
SDL2ãšGDI +ã®äž¡æ¹ã§ç»åãããŒãã§ããŸãã ãã ããSDLã®å ŽåãJPGããã³PNGãèªã¿èŸŒããšãSDL_imageãšããè¿œå ã®äŸåé¢ä¿ã衚瀺ãããŸãã ãããžã§ã¯ããSDLã§ãã«ãããå Žåã¯ã stb_image.hã䜿çšããŠãã ãã ã
GDI +ã§ã¯ããã¹ãŠãããŸãããããã§ããããŸããã ã€ãŸããNuklearã®GDI +ãã©ã€ããŒã¯ãGDI +ã䜿çšããŠç»åãæç»ã§ããŸããã§ããã ç»åã䜿ã£ãŠäœæ¥ãæãäžããèªåã§å®è£ ããå¿ èŠããããŸããïŒ Pull Request ïŒã ããã§ãã¹ãŠãä¿®æ£ãããã³ãŒããå ¬åŒãªããžããªã«è¿œå ãããŸããã
struct nk_image dxNkLoadImageFromMem(const void* buf, int bufSize){ int x,y,n; GLuint tex; unsigned char *data = stbi_load_from_memory(buf, bufSize, &x, &y, &n, 0); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); return nk_image_id((int)tex); }
ã¢ããªã®å€èŠ³
ãã§ãã¯ããã¯ã¹ã®å€èŠ³ãå€æŽããããã«ãNuklearã«ã¯ã¹ã¿ã€ã«èšå®ã¡ã«ããºã ããããŸãã ããã§ã¯ããªã³ãšãªãã®ãã§ãã¯ããã¯ã¹ã¯å¥ã ã®PNGç»åã§ãã åãã³ãŒãã§ãNuklearã®äŸïŒãã¡ã€ã«style.c ïŒããã®èµ€ãããŒããå ¬éãããŠããŸãïŒ
nk_image checked = dxNkLoadImageFromMem( (void*)checked_image, sizeof(checked_image) ); nk_image unchecked = dxNkLoadImageFromMem( (void*)unchecked_image, sizeof(unchecked_image) ); set_style(ctx, THEME_RED); {struct nk_style_toggle *toggle; toggle = &ctx->style.checkbox; toggle->border = -2; /* cursor must overlap original image */ toggle->normal = nk_style_item_image(unchecked); toggle->hover = nk_style_item_image(unchecked); toggle->active = nk_style_item_image(unchecked); toggle->cursor_normal = nk_style_item_image(checked); toggle->cursor_hover = nk_style_item_image(checked); }
Windowsã¢ããªã±ãŒã·ã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã
Linuxã®å ŽåïŒ
çµæã¯äœã§ããïŒ
- UPX 90kbãå§çž®ããåŸã200kbãã³ã³ãã€ã«ããåŸã®Windows EXEã Linuxã§ã¯ãstb_imageã䜿çšãããããã¢ããªã±ãŒã·ã§ã³ã®ãµã€ãºã¯å¹³åã§100kb倧ãããªããŸãã
- Windowsããã³Linuxã§åäœã確èªããŸããã
- ãã©ã³ããšç»åã¯ãé åãšããŠã¢ããªã±ãŒã·ã§ã³ã¡ã¢ãªã«ä¿åãããŸãã Windowsã®WinAPIã«äŸåããªãäŸåé¢ä¿ã¯ãããŸããã
- ã¢ããªã±ãŒã·ã§ã³ã¹ã¿ã€ã«å€æŽãšã³ãžã³ãæ©èœããŸãã
- PNGãšJPGã¯ãGDI +ãšstb_imageã䜿çšããŠããŒããããŸãã
- ããŒãã£ãªãã©ãããã©ãŒã åºæã®ã³ãŒãã¯ãã¹ãŠå¥ã®ãã¡ã€ã«ã«ç§»åãããŸãã éçºè ã¯ãã¢ããªã±ãŒã·ã§ã³ã®äœæã«éäžããŸãã
æ¢ç¥ã®åé¡
- ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããšã«ç°ãªããã©ã³ãã¹ã ãŒãžã³ã°
- ç°ãªããµã€ãºã®ãã§ãã¯ããã¯ã¹
- ç°ãªãç»åã®ãµããŒãïŒstb_imageã䜿çšããå Žåãåé¡ã®ããç»åã¯é¿ããŠãã ããïŒ
- åãæšãŠããããã©ã³ãã§ã®å®å šãªUnicodeãµããŒãã§ã¯ãããŸãã
- Mac OS Xãã¯ãããžãŒã®äŸã¯ãããŸãã
ãã¹ããã©ã¯ãã£ã¹ã®äœ¿çšæ¹æ³
- ãªããžããªhttps://github.com/DeXP/nuklear_crossããããžã§ã¯ãã«ã¯ããŒã³ããŸã
- ãnuklear_cross / nuklear_cross.hããæ¥ç¶ããããããé¢æ°ã䜿çšããŸã
ãããã«
ã¢ããªã±ãŒã·ã§ã³ã¯ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«ãã£ãŠå°ãç°ãªããŸãã ããããéãã¯ãããã§ãããåŸãããçµæã¯ç§ãæºè¶³ãããŸããã Nuklearã¯ãããã¹ããè¡ããªããŠãã©ãã§ãæ©èœããã¯ãã§ããã«ããŽãªã«ã¯ãããŸããã ãã ãããäœãå¿ èŠãªå Žå-ç°¡åã«è¿œå ããŸãããšããã«ããŽãªã«åé¡ãããŸãã
䟿å©ãªãªã³ã¯
- githubã®Nuklear
- Nuklear Webãã¢
- éçºãããdxBin2hãŠãŒãã£ãªãã£ã®ã³ãŒã
- GDI +ãã©ã€ããŒãæ£ããåäœããããã«ç·šéãããªã¹ã
- Nuklearã®ãªãªãŒã¹ãçºè¡šããGameDevãã©ãŒã©ã ã¹ã¬ãã
- å³æã¢ãŒãGUIã®ãŠãŒãã£ãªãã£ã«é¢ããè°è«
- ImGUIã§ã¢ããªã±ãŒã·ã§ã³ãäœæããäŸ
- ãã®æçš¿ã¯è±èªã§ãã
UPD ïŒWebãã¢ãè¿œå ãããã©ã€ãã©ãªããªã³ã©ã€ã³ã§ã©ã€ãã§èŠèŽã§ããããã«ãªããŸããã