diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9427716..1052ef0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,26 +1,16 @@ -name: Run tests +name: Github Actions on: [push, pull_request] jobs: build: - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] - steps: - - uses: actions/checkout@v1 - - - name: Cache choosenim - id: cache-choosenim - uses: actions/cache@v1 - with: - path: ~/.choosenim - key: ${{ runner.os }}-choosenim-stable - - - name: Cache nimble - id: cache-nimble - uses: actions/cache@v1 - with: - path: ~/.nimble - key: ${{ runner.os }}-nimble-stable + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 - uses: jiro4989/setup-nim-action@v1 - - run: nimble test -y + - run: nimble test --gc:orc -y diff --git a/.gitignore b/.gitignore index 9e74f1c..bae492e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ nimcache *.pdb *.ilk .* +*.dll +__pycache__ +bindings/generated diff --git a/LICENSE b/LICENSE index 325bdaf..c5128f1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2021 Author +Copyright (c) 2021 Andre von Houck and Ryan Oldenburg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 0b5f5ee..0d08ce7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,3 @@ -# You can use this nim template to jump start your nim library or project. +# Windy -This template includes: -* MIT licence -* src directory and a private common.nim -* test directory -* GitHub Actions to run the tests on GitHub +This library is still in development and is not ready to be used. diff --git a/bindings/bindings.nim b/bindings/bindings.nim new file mode 100644 index 0000000..06d325a --- /dev/null +++ b/bindings/bindings.nim @@ -0,0 +1,44 @@ +import genny, windy + +var lastError: ref WindyError + +proc takeError(): string = + result = lastError.msg + lastError = nil + +proc checkError(): bool = + result = lastError != nil + +proc isVisible(window: Window): bool = + window.visible + +proc show(window: Window) = + window.visible = true + +proc hide(window: Window) = + window.visible = false + +exportProcs: + checkError + takeError + +exportRefObject App: + discard + +exportRefObject Window: + constructor: + newWindow + procs: + show + hide + isVisible + makeContextCurrent + swapBuffers + +exportProcs: + getApp + init + +writeFiles("bindings/generated", "Windy") + +include generated/internal diff --git a/examples/basic.nim b/examples/basic.nim new file mode 100644 index 0000000..3bb16db --- /dev/null +++ b/examples/basic.nim @@ -0,0 +1,31 @@ +import boxy, opengl, windy + +let app = getApp() +app.init() + +let + windowSize = ivec2(1280, 800) + window = app.newWindow("Windy + Boxy", windowSize.x, windowSize.y) + +window.makeContextCurrent() +loadExtensions() + +window.visible = true + +echo "GL_VERSION: ", cast[cstring](glGetString(GL_VERSION)) +echo "GL_VENDOR: ", cast[cstring](glGetString(GL_VENDOR)) +echo "GL_RENDERER: ", cast[cstring](glGetString(GL_RENDERER)) +echo "GL_SHADING_LANGUAGE_VERSION: ", cast[cstring](glGetString(GL_SHADING_LANGUAGE_VERSION)) + +let bxy = newBoxy() + +proc display() = + bxy.beginFrame(windowSize) + bxy.drawRect(rect(vec2(0, 0), windowSize.vec2), color(1, 1, 1, 1)) + bxy.drawRect(rect(vec2(100, 100), vec2(200, 200)), color(1, 0, 1, 1)) + bxy.endFrame() + window.swapBuffers() + +while true: + # pollEvents() + display() diff --git a/examples/example.nim b/examples/example.nim deleted file mode 100644 index 0262224..0000000 --- a/examples/example.nim +++ /dev/null @@ -1 +0,0 @@ -## Include an example on how to use your library diff --git a/nimtemplate.nimble b/nimtemplate.nimble deleted file mode 100644 index bd72628..0000000 --- a/nimtemplate.nimble +++ /dev/null @@ -1,8 +0,0 @@ -version = "0.0.0" -author = "Your name" -description = "Description of your library" -license = "MIT" - -srcDir = "src" - -requires "nim >= 1.2.2" diff --git a/src/nimtemplate.nim b/src/nimtemplate.nim deleted file mode 100644 index 5fcd576..0000000 --- a/src/nimtemplate.nim +++ /dev/null @@ -1,3 +0,0 @@ -## Public interface to you library. - -import nimtemplate/common diff --git a/src/nimtemplate/common.nim b/src/nimtemplate/common.nim deleted file mode 100644 index 869f4b5..0000000 --- a/src/nimtemplate/common.nim +++ /dev/null @@ -1 +0,0 @@ -## Add private variables or functions here that you don't want to export. diff --git a/src/windy.nim b/src/windy.nim new file mode 100644 index 0000000..49867a6 --- /dev/null +++ b/src/windy.nim @@ -0,0 +1,44 @@ +import windy/common + +export common + +when defined(windows): + import windy/platforms/win32/platform + +type + App* = ref object + platform: PlatformApp + + Window* = ref object + platform: PlatformWindow + +let app = App() + +proc getApp*(): App = + app + +proc init*(app: App) {.raises: [WindyError]} = + if app.platform != nil: + raise newException(WindyError, "Windy is already initialized") + app.platform = newPlatformApp() + +proc newWindow*( + app: App, windowTitle: string, width, height: int +): Window {.raises: [WindyError]} = + result = Window() + result.platform = app.platform.newWindow(windowTitle, width, height) + +proc makeContextCurrent*(window: Window) {.raises: [WindyError]} = + window.platform.makeContextCurrent() + +proc swapBuffers*(window: Window) {.raises: [WindyError]} = + window.platform.swapBuffers() + +proc `visible`*(window: Window): bool = + discard + +proc `visible=`*(window: Window, visible: bool) = + if visible: + window.platform.show() + else: + window.platform.hide() diff --git a/src/windy/common.nim b/src/windy/common.nim new file mode 100644 index 0000000..6903845 --- /dev/null +++ b/src/windy/common.nim @@ -0,0 +1 @@ +type WindyError* = object of ValueError diff --git a/src/windy/platforms/win32/platform.nim b/src/windy/platforms/win32/platform.nim new file mode 100644 index 0000000..273478c --- /dev/null +++ b/src/windy/platforms/win32/platform.nim @@ -0,0 +1,319 @@ +import ../../common, windefs + +const + windowClassName = "WINDY0" + + WGL_DRAW_TO_WINDOW_ARB = 0x2001 + WGL_ACCELERATION_ARB = 0x2003 + WGL_SUPPORT_OPENGL_ARB = 0x2010 + WGL_DOUBLE_BUFFER_ARB = 0x2011 + WGL_PIXEL_TYPE_ARB = 0x2013 + WGL_COLOR_BITS_ARB = 0x2014 + WGL_DEPTH_BITS_ARB = 0x2022 + WGL_STENCIL_BITS_ARB = 0x2023 + WGL_FULL_ACCELERATION_ARB = 0x2027 + WGL_TYPE_RGBA_ARB = 0x202B + + WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091 + WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092 + WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126 + WGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001 + +type + PlatformApp* = ref object + windows*: seq[PlatformWindow] + + PlatformWindow* = ref object + hWnd: HWND + hdc: HDC + hglrc: HGLRC + +var + wglCreateContext: wglCreateContext + wglDeleteContext: wglDeleteContext + wglGetProcAddress: wglGetProcAddress + wglGetCurrentDC: wglGetCurrentDC + wglGetCurrentContext: wglGetCurrentContext + wglMakeCurrent: wglMakeCurrent + wglCreateContextAttribsARB: wglCreateContextAttribsARB + wglChoosePixelFormatARB: wglChoosePixelFormatARB + +proc wstr*(str: string): string = + let wlen = MultiByteToWideChar( + CP_UTF8, + 0, + str[0].unsafeAddr, + str.len.int32, + nil, + 0 + ) + result = newString(wlen * 2 + 1) + discard MultiByteToWideChar( + CP_UTF8, + 0, + str[0].unsafeAddr, + str.len.int32, + cast[ptr WCHAR](result[0].addr), + wlen + ) + +proc registerWindowClass(windowClassName: string, wndProc: WNDPROC) = + let windowClassName = windowClassName.wstr() + + var wc: WNDCLASSEXW + wc.cbSize = sizeof(WNDCLASSEXW).UINT + wc.style = CS_HREDRAW or CS_VREDRAW or CS_DBLCLKS + wc.lpfnWndProc = wndProc + wc.hInstance = GetModuleHandleW(nil) + wc.hCursor = LoadCursorW(0, IDC_ARROW) + wc.lpszClassName = cast[ptr WCHAR](windowClassName[0].unsafeAddr) + wc.hIcon = LoadImageW( + 0, + IDI_APPLICATION, + IMAGE_ICON, + 0, + 0, + LR_DEFAULTSIZE or LR_SHARED + ) + + if RegisterClassExW(wc.addr) == 0: + raise newException(WindyError, "Error registering window class") + +proc createWindow( + windowClassName, windowTitle: string, x, y, w, h: int +): HWND = + let + windowClassName = windowClassName.wstr() + windowTitle = windowTitle.wstr() + + result = CreateWindowExW( + WS_EX_APPWINDOW, + cast[ptr WCHAR](windowClassName[0].unsafeAddr), + cast[ptr WCHAR](windowTitle[0].unsafeAddr), + WS_OVERLAPPEDWINDOW, + x.int32, + y.int32, + w.int32, + h.int32, + 0, + 0, + GetModuleHandleW(nil), + nil + ) + if result == 0: + raise newException(WindyError, "Creating native window failed") + +proc getDC(hWnd: HWND): HDC = + result = GetDC(hWnd) + if result == 0: + raise newException(WindyError, "Error getting window DC") + +proc makeContextCurrent(hdc: HDC, hglrc: HGLRC) = + if wglMakeCurrent(hdc, hglrc) == 0: + raise newException(WindyError, "Error activating OpenGL rendering context") + +proc loadOpenGL() = + let opengl = LoadLibraryA("opengl32.dll") + if opengl == 0: + raise newException(WindyError, "Loading opengl32.dll failed") + + wglCreateContext = + cast[wglCreateContext](GetProcAddress(opengl, "wglCreateContext")) + wglDeleteContext = + cast[wglDeleteContext](GetProcAddress(opengl, "wglDeleteContext")) + wglGetProcAddress = + cast[wglGetProcAddress](GetProcAddress(opengl, "wglGetProcAddress")) + wglGetCurrentDC = + cast[wglGetCurrentDC](GetProcAddress(opengl, "wglGetCurrentDC")) + wglGetCurrentContext = + cast[wglGetCurrentContext](GetProcAddress(opengl, "wglGetCurrentContext")) + wglMakeCurrent = + cast[wglMakeCurrent](GetProcAddress(opengl, "wglMakeCurrent")) + + # Before we can load extensions, we need a dummy OpenGL context, created using + # a dummy window. We use a dummy window because you can only set the pixel + # format for a window once. For the real window, we want to use + # wglChoosePixelFormatARB (so we can potentially specify options that aren't + # available in PIXELFORMATDESCRIPTOR), but we can't load and use that before + # we have a context. + + let dummyWindowClassName = "WindyDummy" + + proc dummyWndProc( + hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM + ): LRESULT {.stdcall.} = + DefWindowProcW(hWnd, uMsg, wParam, lParam) + + registerWindowClass(dummyWindowClassName, dummyWndProc) + + let + hWnd = createWindow( + dummyWindowClassName, + dummyWindowClassName, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT + ) + hdc = getDC(hWnd) + + var pfd: PIXELFORMATDESCRIPTOR + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR).WORD + pfd.nVersion = 1 + pfd.dwFlags = PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER + pfd.iPixelType = PFD_TYPE_RGBA + pfd.cColorBits = 32 + pfd.cAlphaBits = 8 + pfd.cDepthBits = 24 + pfd.cStencilBits = 8 + + let pixelFormat = ChoosePixelFormat(hdc, pfd.addr) + if pixelFormat == 0: + raise newException(WindyError, "Error choosing pixel format") + + if SetPixelFormat(hdc, pixelFormat, pfd.addr) == 0: + raise newException(WindyError, "Error setting pixel format") + + let hglrc = wglCreateContext(hdc) + if hglrc == 0: + raise newException(WindyError, "Error creating rendering context") + + makeContextCurrent(hdc, hglrc) + + wglCreateContextAttribsARB = + cast[wglCreateContextAttribsARB]( + wglGetProcAddress("wglCreateContextAttribsARB") + ) + wglChoosePixelFormatARB = + cast[wglChoosePixelFormatARB]( + wglGetProcAddress("wglChoosePixelFormatARB") + ) + + discard wglMakeCurrent(hdc, 0) + discard wglDeleteContext(hglrc) + discard ReleaseDC(hWnd, hdc) + discard DestroyWindow(hWnd) + +proc wndProc( + hWnd: HWND, + uMsg: UINT, + wParam: WPARAM, + lParam: LPARAM +): LRESULT {.stdcall.} = + DefWindowProcW(hWnd, uMsg, wParam, lParam) + +proc newPlatformApp*(): PlatformApp = + result = PlatformApp() + loadOpenGL() + registerWindowClass(windowClassName, wndProc) + +proc show*(window: PlatformWindow) = + discard ShowWindow(window.hWnd, SW_SHOW) + +proc hide*(window: PlatformWindow) = + discard ShowWindow(window.hWnd, SW_HIDE) + +proc makeContextCurrent*(window: PlatformWindow) = + makeContextCurrent(window.hdc, window.hglrc) + +proc swapBuffers*(window: PlatformWindow) = + if SwapBuffers(window.hdc) == 0: + raise newException(WindyError, "Error swapping buffers") + +proc newWindow*( + app: PlatformApp, + windowTitle: string, + x, y, w, h: int +): PlatformWindow = + result = PlatformWindow() + result.hWnd = createWindow( + windowClassName, + windowTitle, + x, + y, + w, + h + ) + result.hdc = getDC(result.hWnd) + + const GL_TRUE = 1 + let pixelFormatAttribs = [ + WGL_DRAW_TO_WINDOW_ARB.int32, + GL_TRUE, + WGL_SUPPORT_OPENGL_ARB, + GL_TRUE, + WGL_DOUBLE_BUFFER_ARB, + GL_TRUE, + WGL_ACCELERATION_ARB, + WGL_FULL_ACCELERATION_ARB, + WGL_PIXEL_TYPE_ARB, + WGL_TYPE_RGBA_ARB, + WGL_COLOR_BITS_ARB, + 32, + WGL_DEPTH_BITS_ARB, + 24, + WGL_STENCIL_BITS_ARB, + 8, + 0 + ] + + var + pixelFormat: int32 + numFormats: UINT + if wglChoosePixelFormatARB( + result.hdc, + pixelFormatAttribs[0].unsafeAddr, + nil, + 1, + pixelFormat.addr, + numFormats.addr + ) == 0: + raise newException(WindyError, "Error choosing pixel format") + + if numFormats == 0: + raise newException(WindyError, "No pixel format chosen") + + var pfd: PIXELFORMATDESCRIPTOR + if DescribePixelFormat( + result.hdc, + pixelFormat, + sizeof(PIXELFORMATDESCRIPTOR).UINT, + pfd.addr + ) == 0: + raise newException(WindyError, "Error describing pixel format") + + if SetPixelFormat(result.hdc, pixelFormat, pfd.addr) == 0: + raise newException(WindyError, "Error setting pixel format") + + let contextAttribs = [ + WGL_CONTEXT_MAJOR_VERSION_ARB.int32, + 4, + WGL_CONTEXT_MINOR_VERSION_ARB, + 1, + WGL_CONTEXT_PROFILE_MASK_ARB, + WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0 + ] + + result.hglrc = wglCreateContextAttribsARB( + result.hdc, + 0, + contextAttribs[0].unsafeAddr + ) + if result.hglrc == 0: + raise newException(WindyError, "Error creating OpenGL context") + + # The first call to ShowWindow may ignore the parameter so do an initial + # call to clear that behavior. + result.hide() + + result.makeContextCurrent() + + app.windows.add(result) + +proc newWindow*( + app: PlatformApp, + windowTitle: string, + width, height: int +): PlatformWindow = + app.newWindow(windowTitle, CW_USEDEFAULT, CW_USEDEFAULT, width, height) diff --git a/src/windy/platforms/win32/windefs.nim b/src/windy/platforms/win32/windefs.nim new file mode 100644 index 0000000..b863bf9 --- /dev/null +++ b/src/windy/platforms/win32/windefs.nim @@ -0,0 +1,313 @@ +when defined(cpu64): + type + UINT_PTR* = int64 + LONG_PTR* = int64 +else: + type + UINT_PTR* = int32 + LONG_PTR* = int32 + +type + BYTE* = uint8 + BOOL* = int32 + LONG* = int32 + WORD* = uint16 + ATOM* = WORD + DWORD* = int32 + LPCSTR* = cstring + WCHAR* = uint16 + LPCCH* = cstring + LPCWSTR* = ptr WCHAR + LPWSTR* = ptr WCHAR + HANDLE* = int + HWND* = HANDLE + HMENU* = HANDLE + HINSTANCE* = HANDLE + HDC* = HANDLE + HGLRC* = HANDLE + HICON* = HANDLE + HCURSOR* = HICON + HBRUSH* = HANDLE + HMODULE* = HINSTANCE + LPVOID* = pointer + UINT* = uint32 + WPARAM* = UINT_PTR + LPARAM* = LONG_PTR + LRESULT* = LONG_PTR + WNDPROC* = proc ( + hWnd: HWND, + uMsg: UINT, + wParam: WPARAM, + lParam: LPARAM + ): LRESULT {.stdcall.} + WNDCLASSEXW* {.pure.} = object + cbSize*: UINT + style*: UINT + lpfnWndProc*: WNDPROC + cbClsExtra*: int32 + cbWndExtra*: int32 + hInstance*: HINSTANCE + hIcon*: HICON + hCursor*: HCURSOR + hbrBackground*: HBRUSH + lpszMenuName*: LPCWSTR + lpszClassName*: LPCWSTR + hIconSm*: HICON + LPWNDCLASSEXW* = ptr WNDCLASSEXW + POINT* {.pure.} = object + x*: LONG + y*: LONG + MSG* {.pure.} = object + hwnd*: HWND + message*: UINT + wParam*: WPARAM + lParam*: LPARAM + time*: DWORD + pt*: POINT + LPMSG* = ptr MSG + PROC* = pointer + FARPROC* = pointer + wglCreateContext* = proc(hdc: HDC): HGLRC {.stdcall, raises: [].} + wglDeleteContext* = proc(hglrc: HGLRC): BOOL {.stdcall, raises: [].} + wglGetProcAddress* = proc(lpProcName: LPCSTR): PROC {.stdcall, raises: [].} + wglGetCurrentDC* = proc(): HDC {.stdcall, raises: [].} + wglGetCurrentContext* = proc(): HGLRC {.stdcall, raises: [].} + wglMakeCurrent* = proc(hdc: HDC, hglrc: HGLRC): BOOL {.stdcall, raises: [].} + wglCreateContextAttribsARB* = proc( + hdc: HDC, + hShareContext: HGLRC, + attribList: ptr int32 + ): HGLRC {.stdcall, raises: [].} + wglChoosePixelFormatARB* = proc( + hdc: HDC, + piAttribIList: ptr int32, + pfAttribFList: ptr float32, + nMaxFormats: UINT, + piFormats: ptr int32, + nNumFormats: ptr UINT + ): BOOL {.stdcall, raises: [].} + PIXELFORMATDESCRIPTOR* {.pure.} = object + nSize*: WORD + nVersion*: WORD + dwFlags*: DWORD + iPixelType*: BYTE + cColorBits*: BYTE + cRedBits*: BYTE + cRedShift*: BYTE + cGreenBits*: BYTE + cGreenShift*: BYTE + cBlueBits*: BYTE + cBlueShift*: BYTE + cAlphaBits*: BYTE + cAlphaShift*: BYTE + cAccumBits*: BYTE + cAccumRedBits*: BYTE + cAccumGreenBits*: BYTE + cAccumBlueBits*: BYTE + cAccumAlphaBits*: BYTE + cDepthBits*: BYTE + cStencilBits*: BYTE + cAuxBuffers*: BYTE + iLayerType*: BYTE + bReserved*: BYTE + dwLayerMask*: DWORD + dwVisibleMask*: DWORD + dwDamageMask*: DWORD + +template MAKEINTRESOURCE*(i: untyped): untyped = cast[LPWSTR](i and 0xffff) + +const + CP_UTF8* = 65001 + CS_VREDRAW* = 0x0001 + CS_HREDRAW* = 0x0002 + CS_DBLCLKS* = 0x0008 + IDC_ARROW* = MAKEINTRESOURCE(32512) + IDI_APPLICATION* = MAKEINTRESOURCE(32512) + IMAGE_ICON* = 1 + LR_DEFAULTSIZE* = 0x0040 + LR_SHARED* = 0x8000 + CW_USEDEFAULT* = 0x80000000'i32 + WS_OVERLAPPED* = 0x00000000 + WS_POPUP* = 0x80000000'i32 + WS_CHILD* = 0x40000000 + WS_MINIMIZE* = 0x20000000 + WS_VISIBLE* = 0x10000000 + WS_DISABLED* = 0x08000000 + WS_CLIPSIBLINGS* = 0x04000000 + WS_CLIPCHILDREN* = 0x02000000 + WS_MAXIMIZE* = 0x01000000 + WS_CAPTION* = 0x00C00000 + WS_BORDER* = 0x00800000 + WS_DLGFRAME* = 0x00400000 + WS_VSCROLL* = 0x00200000 + WS_HSCROLL* = 0x00100000 + WS_SYSMENU* = 0x00080000 + WS_THICKFRAME* = 0x00040000 + WS_GROUP* = 0x00020000 + WS_TABSTOP* = 0x00010000 + WS_MINIMIZEBOX* = 0x00020000 + WS_MAXIMIZEBOX* = 0x00010000 + WS_TILED* = WS_OVERLAPPED + WS_ICONIC* = WS_MINIMIZE + WS_SIZEBOX* = WS_THICKFRAME + WS_OVERLAPPEDWINDOW* = WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX + WS_TILEDWINDOW* = WS_OVERLAPPEDWINDOW + WS_POPUPWINDOW* = WS_POPUP or WS_BORDER or WS_SYSMENU + WS_CHILDWINDOW* = WS_CHILD + WS_EX_APPWINDOW* = 0x00040000 + WM_NULL* = 0x0000 + WM_CREATE* = 0x0001 + WM_DESTROY* = 0x0002 + WM_CLOSE* = 0x0010 + WM_QUIT* = 0x0012 + WM_NCCREATE* = 0x0081 + WM_NCCALCSIZE* = 0x0083 + SW_HIDE* = 0 + SW_SHOWNORMAL* = 1 + SW_NORMAL* = 1 + SW_SHOWMINIMIZED* = 2 + SW_SHOWMAXIMIZED* = 3 + SW_MAXIMIZE* = 3 + SW_SHOWNOACTIVATE* = 4 + SW_SHOW* = 5 + SW_MINIMIZE* = 6 + SW_SHOWMINNOACTIVE* = 7 + SW_SHOWNA* = 8 + SW_RESTORE* = 9 + SW_SHOWDEFAULT* = 10 + SW_FORCEMINIMIZE* = 11 + PM_NOREMOVE* = 0x0000 + PM_REMOVE* = 0x0001 + PM_NOYIELD* = 0x0002 + PFD_DRAW_TO_WINDOW* = 0x00000004 + PFD_SUPPORT_OPENGL* = 0x00000020 + PFD_DOUBLEBUFFER* = 0x00000001 + PFD_TYPE_RGBA* = 0 + +proc GetLastError*(): DWORD {.importc, stdcall, dynlib: "Kernel32".} + +proc MultiByteToWideChar*( + codePage: UINT, + dwFlags: DWORD, + lpMultiByteStr: LPCCH, + cbMultiByte: int32, + lpWideCharStr: LPWSTR, + cchWideChar: int32 +): int32 {.importc, stdcall, dynlib: "Kernel32".} + +proc LoadLibraryA*( + lpLibFileName: LPCSTR +): HMODULE {.importc, stdcall, dynlib: "Kernel32".} + +proc FreeLibrary*( + hLibModule: HMODULE +): BOOL {.importc, stdcall, dynlib: "Kernel32".} + +proc GetProcAddress*( + hModule: HMODULE, + lpProcName: LPCSTR +): FARPROC {.importc, stdcall, dynlib: "Kernel32".} + +proc GetModuleHandleW*( + lpModuleName: LPCWSTR +): HMODULE {.importc, stdcall, dynlib: "Kernel32".} + +proc LoadCursorW*( + hInstance: HINSTANCE, + lpCursorName: LPCWSTR +): HCURSOR {.importc, stdcall, dynlib: "User32".} + +proc LoadImageW*( + hInstance: HINSTANCE, + name: LPCWSTR, + `type`: UINT, + cx: int32, + cy: int32, + fuLoad: UINT +): HANDLE {.importc, stdcall, dynlib: "User32".} + +proc GetClassInfoExW*( + hInstance: HINSTANCE, + lpszClass: LPCWSTR, + lpwcx: LPWNDCLASSEXW +): BOOL {.importc, stdcall, dynlib: "User32".} + +proc RegisterClassExW*( + P1: ptr WNDCLASSEXW +): ATOM {.importc, stdcall, dynlib: "User32".} + +proc CreateWindowExW*( + dwExStyle: DWORD, + lpClassName: LPCWSTR, + lpWindowName: LPCWSTR, + dwStyle: DWORD, + X: int32, + Y: int32, + nWidth: int32, + nHeight: int32, + hWndParent: HWND, + hMenu: HMENU, + hInstance: HINSTANCE, + lpParam: LPVOID +): HWND {.importc, stdcall, dynlib: "User32".} + +proc DefWindowProcW*( + hWnd: HWND, + uMsg: UINT, + wParam: WPARAM, + lParam: LPARAM +): LRESULT {.importc, stdcall, dynlib: "User32".} + +proc ShowWindow*( + hWnd: HWND, + nCmdShow: int32 +): BOOL {.importc, stdcall, dynlib: "User32".} + +proc PeekMessageW*( + lpMsg: LPMSG, + hWnd: HWND, + wMsgFilterMin: UINT, + wMsgFilterMax: UINT, + wRemoveMsg: UINT +): BOOL {.importc, stdcall, dynlib: "User32".} + +proc TranslateMessage*( + lpMsg: LPMSG +): BOOL {.importc, stdcall, dynlib: "User32".} + +proc DispatchMessageW*( + lpMsg: LPMSG +): LRESULT {.importc, stdcall, dynlib: "User32".} + +proc GetActiveWindow*(): HWND {.importc, stdcall, dynlib: "User32".} + +proc DestroyWindow*(hWnd: HWND): BOOL {.importc, stdcall, dynlib: "User32".} + +proc GetDC*(hWnd: HWND): HDC {.importc, stdcall, dynlib: "User32".} + +proc ReleaseDC*( + hWnd: HWND, + hdc: HDC +): BOOL {.importc, stdcall, dynlib: "User32".} + +proc ChoosePixelFormat*( + hdc: HDC, + ppfd: ptr PIXELFORMATDESCRIPTOR +): int32 {.importc, stdcall, dynlib: "Gdi32".} + +proc SetPixelFormat*( + hdc: HDC, + format: int32, + ppfd: ptr PIXELFORMATDESCRIPTOR +): BOOL {.importc, stdcall, dynlib: "Gdi32".} + +proc GetPixelFormat*(hdc: HDC): int32 {.importc, stdcall, dynlib: "Gdi32".} + +proc DescribePixelFormat*( + hdc: HDC, + iPixelFormat: int32, + nBytes: UINT, + ppfd: ptr PIXELFORMATDESCRIPTOR +): int32 {.importc, stdcall, dynlib: "Gdi32".} + +proc SwapBuffers*(hdc: HDC): BOOL {.importc, stdcall, dynlib: "Gdi32".} diff --git a/tests/test.nim b/tests/test.nim index 41fa755..e69de29 100644 --- a/tests/test.nim +++ b/tests/test.nim @@ -1,3 +0,0 @@ -## Put your tests here. - -import nimtemplate diff --git a/windy.nimble b/windy.nimble new file mode 100644 index 0000000..3d64c36 --- /dev/null +++ b/windy.nimble @@ -0,0 +1,24 @@ +version = "0.0.0" +author = "Andre von Houck and Ryan Oldenburg" +description = "Windy" +license = "MIT" + +srcDir = "src" + +requires "nim >= 1.4.8" + +task bindings, "Generate bindings": + + proc compile(libName: string, flags = "") = + exec "nim c -f " & flags & " -d:release -d:noAutoGLerrorCheck --app:lib --gc:arc --tlsEmulation:off --out:" & libName & " --outdir:bindings/generated bindings/bindings.nim" + + when defined(windows): + compile "windy.dll" + + elif defined(macosx): + compile "libwindy.dylib.arm", "-l:'-target arm64-apple-macos11' -t:'-target arm64-apple-macos11'" + compile "libwindy.dylib.x64", "-l:'-target x86_64-apple-macos10.12' -t:'-target x86_64-apple-macos10.12'" + exec "lipo bindings/generated/libwindy.dylib.arm bindings/generated/libwindy.dylib.x64 -output bindings/generated/libwindy.dylib -create" + + else: + compile "libwindy.so"