diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /platform/windows | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) |
GODOT IS OPEN SOURCE
Diffstat (limited to 'platform/windows')
-rw-r--r-- | platform/windows/SCsub | 13 | ||||
-rw-r--r-- | platform/windows/context_gl_win.cpp | 205 | ||||
-rw-r--r-- | platform/windows/context_gl_win.h | 79 | ||||
-rw-r--r-- | platform/windows/ctxgl_procaddr.cpp | 186 | ||||
-rw-r--r-- | platform/windows/ctxgl_procaddr.h | 38 | ||||
-rw-r--r-- | platform/windows/detect.py | 208 | ||||
-rw-r--r-- | platform/windows/export/export.cpp | 24 | ||||
-rw-r--r-- | platform/windows/export/export.h | 3 | ||||
-rw-r--r-- | platform/windows/godot_win.cpp | 207 | ||||
-rw-r--r-- | platform/windows/key_mapping_win.cpp | 256 | ||||
-rw-r--r-- | platform/windows/key_mapping_win.h | 51 | ||||
-rw-r--r-- | platform/windows/lang_table.h | 190 | ||||
-rw-r--r-- | platform/windows/logo.png | bin | 0 -> 1434 bytes | |||
-rw-r--r-- | platform/windows/os_windows.cpp | 1732 | ||||
-rw-r--r-- | platform/windows/os_windows.h | 257 | ||||
-rw-r--r-- | platform/windows/platform_config.h | 35 | ||||
-rw-r--r-- | platform/windows/stream_peer_winsock.cpp | 368 | ||||
-rw-r--r-- | platform/windows/stream_peer_winsock.h | 90 | ||||
-rw-r--r-- | platform/windows/tcp_server_winsock.cpp | 166 | ||||
-rw-r--r-- | platform/windows/tcp_server_winsock.h | 55 |
20 files changed, 4163 insertions, 0 deletions
diff --git a/platform/windows/SCsub b/platform/windows/SCsub new file mode 100644 index 0000000000..1d454e40c2 --- /dev/null +++ b/platform/windows/SCsub @@ -0,0 +1,13 @@ +Import('env') + + +common_win=[ + "context_gl_win.cpp", + "os_windows.cpp", + "ctxgl_procaddr.cpp", + "key_mapping_win.cpp", + "tcp_server_winsock.cpp", + "stream_peer_winsock.cpp", +] + +env.Program('#bin/godot.exe',['godot_win.cpp']+common_win) diff --git a/platform/windows/context_gl_win.cpp b/platform/windows/context_gl_win.cpp new file mode 100644 index 0000000000..a8f74fde2c --- /dev/null +++ b/platform/windows/context_gl_win.cpp @@ -0,0 +1,205 @@ +/*************************************************************************/ +/* context_gl_win.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED) + +// +// C++ Implementation: context_gl_x11 +// +// Description: +// +// +// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#define WINVER 0x0500 +#include "context_gl_win.h" + +//#include "drivers/opengl/glwrapper.h" +//#include "ctxgl_procaddr.h" + +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 + +typedef HGLRC (APIENTRY* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*); + + +void ContextGL_Win::release_current() { + + + wglMakeCurrent(hDC,NULL); + +} + + +void ContextGL_Win::make_current() { + + wglMakeCurrent(hDC,hRC); +} + +int ContextGL_Win::get_window_width() { + + return OS::get_singleton()->get_video_mode().width; +} + +int ContextGL_Win::get_window_height() { + + return OS::get_singleton()->get_video_mode().height; +} + +void ContextGL_Win::swap_buffers() { + + SwapBuffers(hDC); +} + +/* +static GLWrapperFuncPtr wrapper_get_proc_address(const char* p_function) { + + print_line(String()+"getting proc of: "+p_function); + GLWrapperFuncPtr func=(GLWrapperFuncPtr)get_gl_proc_address(p_function); + if (!func) { + print_line("Couldn't find function: "+String(p_function)); + print_line("error: "+itos(GetLastError())); + } + return func; + +} +*/ + + +Error ContextGL_Win::initialize() { + + static PIXELFORMATDESCRIPTOR pfd= { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 24, + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0,// No Alpha Buffer + 0,// Shift Bit Ignored + 0,// No Accumulation Buffer + 0, 0, 0, 0,// Accumulation Bits Ignored + 24,// 24Bit Z-Buffer (Depth Buffer) + 0,// No Stencil Buffer + 0,// No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0,// Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + if (!(hDC=GetDC(hWnd))) { + MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return ERR_CANT_CREATE; // Return FALSE + } + + if (!(pixel_format=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format? + { + MessageBox(NULL,"Can't Find A Suitable pixel_format.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return ERR_CANT_CREATE; // Return FALSE + } + + if(!SetPixelFormat(hDC,pixel_format,&pfd)) // Are We Able To Set The Pixel Format? + { + MessageBox(NULL,"Can't Set The pixel_format.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return ERR_CANT_CREATE; // Return FALSE + } + + if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context? + { + MessageBox(NULL,"Can't Create A Temporary GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return ERR_CANT_CREATE; // Return FALSE + } + + wglMakeCurrent(hDC,hRC); + + if (opengl_3_context) { + + int attribs[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, 3,//we want a 3.1 context + WGL_CONTEXT_MINOR_VERSION_ARB, 2, + //and it shall be forward compatible so that we can only use up to date functionality + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + 0}; //zero indicates the end of the array + + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; //pointer to the method + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB"); + + if(wglCreateContextAttribsARB == NULL) //OpenGL 3.0 is not supported + { + MessageBox(NULL,"Cannot get Proc Adress for CreateContextAttribs", "ERROR",MB_OK|MB_ICONEXCLAMATION); + wglDeleteContext(hRC); + return ERR_CANT_CREATE; + } + + HGLRC new_hRC; + if (!(new_hRC=wglCreateContextAttribsARB(hDC,0, attribs))) + { + wglDeleteContext(hRC); + MessageBox(NULL,"Can't Create An OpenGL 3.1 Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return ERR_CANT_CREATE; // Return false + } + wglMakeCurrent(hDC,NULL); + wglDeleteContext(hRC); + hRC=new_hRC; + + if (!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context + { + MessageBox(NULL,"Can't Activate The GL 3.1 Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return ERR_CANT_CREATE; // Return FALSE + } + + printf("Activated GL 3.1 context"); + } + + +// glWrapperInit(wrapper_get_proc_address); + + return OK; +} + +ContextGL_Win::ContextGL_Win(HWND hwnd,bool p_opengl_3_context) { + + opengl_3_context=p_opengl_3_context; + hWnd=hwnd; +} + +ContextGL_Win::~ContextGL_Win() { + + +} + + +#endif diff --git a/platform/windows/context_gl_win.h b/platform/windows/context_gl_win.h new file mode 100644 index 0000000000..6e8d99a5f0 --- /dev/null +++ b/platform/windows/context_gl_win.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* context_gl_win.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED) +// +// C++ Interface: context_gl_x11 +// +// Description: +// +// +// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#ifndef CONTEXT_GL_WIN_H +#define CONTEXT_GL_WIN_H + + +#include "os/os.h" +#include "drivers/gl_context/context_gl.h" +#include "error_list.h" + +#include <windows.h> + +class ContextGL_Win : public ContextGL { + + HDC hDC; + HGLRC hRC; + unsigned int pixel_format; + HWND hWnd; + bool opengl_3_context; +public: + + + virtual void release_current(); + + virtual void make_current(); + + virtual int get_window_width(); + virtual int get_window_height(); + virtual void swap_buffers(); + + virtual Error initialize(); + + + ContextGL_Win(HWND hwnd,bool p_opengl_3_context); + ~ContextGL_Win(); + +}; + +#endif +#endif diff --git a/platform/windows/ctxgl_procaddr.cpp b/platform/windows/ctxgl_procaddr.cpp new file mode 100644 index 0000000000..9715784c32 --- /dev/null +++ b/platform/windows/ctxgl_procaddr.cpp @@ -0,0 +1,186 @@ +/*************************************************************************/ +/* ctxgl_procaddr.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef OPENGL_ENABLED
+#include "ctxgl_procaddr.h"
+#include <GL/gl.h>
+#include <stdio.h>
+
+static PROC _gl_procs[]={
+ (PROC)glCullFace,
+ (PROC)glFrontFace,
+ (PROC)glHint,
+ (PROC)glLineWidth,
+ (PROC)glPointSize,
+ (PROC)glPolygonMode,
+ (PROC)glScissor,
+ (PROC)glTexParameterf,
+ (PROC)glTexParameterfv,
+ (PROC)glTexParameteri,
+ (PROC)glTexParameteriv,
+ (PROC)glTexImage1D,
+ (PROC)glTexImage2D,
+ (PROC)glDrawBuffer,
+ (PROC)glClear,
+ (PROC)glClearColor,
+ (PROC)glClearStencil,
+ (PROC)glClearDepth,
+ (PROC)glStencilMask,
+ (PROC)glColorMask,
+ (PROC)glDepthMask,
+ (PROC)glDisable,
+ (PROC)glEnable,
+ (PROC)glFinish,
+ (PROC)glFlush,
+ (PROC)glBlendFunc,
+ (PROC)glLogicOp,
+ (PROC)glStencilFunc,
+ (PROC)glStencilOp,
+ (PROC)glDepthFunc,
+ (PROC)glPixelStoref,
+ (PROC)glPixelStorei,
+ (PROC)glReadBuffer,
+ (PROC)glReadPixels,
+ (PROC)glGetBooleanv,
+ (PROC)glGetDoublev,
+ (PROC)glGetError,
+ (PROC)glGetFloatv,
+ (PROC)glGetIntegerv,
+ (PROC)glGetString,
+ (PROC)glGetTexImage,
+ (PROC)glGetTexParameterfv,
+ (PROC)glGetTexParameteriv,
+ (PROC)glGetTexLevelParameterfv,
+ (PROC)glGetTexLevelParameteriv,
+ (PROC)glIsEnabled,
+ (PROC)glDepthRange,
+ (PROC)glViewport,
+ /* not detected in ATI */
+ (PROC)glDrawArrays,
+ (PROC)glDrawElements,
+ (PROC)glGetPointerv,
+ (PROC)glPolygonOffset,
+ (PROC)glCopyTexImage1D,
+ (PROC)glCopyTexImage2D,
+ (PROC)glCopyTexSubImage1D,
+ (PROC)glCopyTexSubImage2D,
+ (PROC)glTexSubImage1D,
+ (PROC)glTexSubImage2D,
+ (PROC)glBindTexture,
+ (PROC)glDeleteTextures,
+ (PROC)glGenTextures,
+ (PROC)glIsTexture,
+
+ 0
+};
+
+static const char* _gl_proc_names[]={
+ "glCullFace",
+ "glFrontFace",
+ "glHint",
+ "glLineWidth",
+ "glPointSize",
+ "glPolygonMode",
+ "glScissor",
+ "glTexParameterf",
+ "glTexParameterfv",
+ "glTexParameteri",
+ "glTexParameteriv",
+ "glTexImage1D",
+ "glTexImage2D",
+ "glDrawBuffer",
+ "glClear",
+ "glClearColor",
+ "glClearStencil",
+ "glClearDepth",
+ "glStencilMask",
+ "glColorMask",
+ "glDepthMask",
+ "glDisable",
+ "glEnable",
+ "glFinish",
+ "glFlush",
+ "glBlendFunc",
+ "glLogicOp",
+ "glStencilFunc",
+ "glStencilOp",
+ "glDepthFunc",
+ "glPixelStoref",
+ "glPixelStorei",
+ "glReadBuffer",
+ "glReadPixels",
+ "glGetBooleanv",
+ "glGetDoublev",
+ "glGetError",
+ "glGetFloatv",
+ "glGetIntegerv",
+ "glGetString",
+ "glGetTexImage",
+ "glGetTexParameterfv",
+ "glGetTexParameteriv",
+ "glGetTexLevelParameterfv",
+ "glGetTexLevelParameteriv",
+ "glIsEnabled",
+ "glDepthRange",
+ "glViewport",
+ /* not detected in ati */
+ "glDrawArrays",
+ "glDrawElements",
+ "glGetPointerv",
+ "glPolygonOffset",
+ "glCopyTexImage1D",
+ "glCopyTexImage2D",
+ "glCopyTexSubImage1D",
+ "glCopyTexSubImage2D",
+ "glTexSubImage1D",
+ "glTexSubImage2D",
+ "glBindTexture",
+ "glDeleteTextures",
+ "glGenTextures",
+ "glIsTexture",
+
+ 0
+};
+
+PROC get_gl_proc_address(const char* p_address) {
+
+ PROC proc = wglGetProcAddress((const CHAR*)p_address);
+ if (!proc) {
+
+ int i=0;
+ while(_gl_procs[i]) {
+
+ if (strcmp(p_address,_gl_proc_names[i])==0) {
+ return _gl_procs[i];
+ }
+ i++;
+ }
+ }
+ return proc;
+}
+#endif
diff --git a/platform/windows/ctxgl_procaddr.h b/platform/windows/ctxgl_procaddr.h new file mode 100644 index 0000000000..d3ab20e82d --- /dev/null +++ b/platform/windows/ctxgl_procaddr.h @@ -0,0 +1,38 @@ +/*************************************************************************/ +/* ctxgl_procaddr.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef CTXGL_PROCADDR_H
+#define CTXGL_PROCADDR_H
+
+#ifdef OPENGL_ENABLED
+#include <windows.h>
+
+
+PROC get_gl_proc_address(const char* p_address);
+#endif
+#endif // CTXGL_PROCADDR_H
diff --git a/platform/windows/detect.py b/platform/windows/detect.py new file mode 100644 index 0000000000..1774ba17f8 --- /dev/null +++ b/platform/windows/detect.py @@ -0,0 +1,208 @@ +
+
+import os
+
+import sys
+
+
+def is_active():
+ return True
+
+def get_name():
+ return "Windows"
+
+def can_build():
+
+
+ if (os.name=="nt"):
+ #building natively on windows!
+ if (os.getenv("VSINSTALLDIR")):
+ return True
+ else:
+ print("MSVC Not detected, attempting mingw.")
+ return True
+
+
+
+ if (os.name=="posix"):
+
+ if os.system("i586-mingw32msvc-gcc --version") == 0:
+ return True
+
+
+ return False
+
+def get_opts():
+
+ mwp=""
+ mwp64=""
+ if (os.name!="nt"):
+ mwp="i586-mingw32msvc-"
+ mwp64="x86_64-w64-mingw32-"
+
+ return [
+ ('force_64_bits','Force 64 bits binary','no'),
+ ('force_32_bits','Force 32 bits binary','no'),
+ ('mingw_prefix','Mingw Prefix',mwp),
+ ('mingw_prefix_64','Mingw Prefix 64 bits',mwp64),
+ ]
+
+def get_flags():
+
+ return [
+ ('freetype','builtin'), #use builtin freetype
+ ]
+
+
+
+def configure(env):
+
+ if os.name == "posix":
+ env['OBJSUFFIX'] = ".win"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = ".win"+env['LIBSUFFIX']
+
+ env.Append(CPPPATH=['#platform/windows'])
+
+ if (env["tools"]=="no"):
+ #no tools suffix
+ env['OBJSUFFIX'] = ".nt"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = ".nt"+env['LIBSUFFIX']
+
+
+ if (os.name=="nt" and os.getenv("VSINSTALLDIR")!=None):
+ #build using visual studio
+ env['ENV']['TMP'] = os.environ['TMP']
+ env.Append(CPPPATH=['#platform/windows/include'])
+ env.Append(LIBPATH=['#platform/windows/lib'])
+
+ if (env["freetype"]!="no"):
+ env.Append(CCFLAGS=['/DFREETYPE_ENABLED'])
+ env.Append(CPPPATH=['#tools/freetype'])
+ env.Append(CPPPATH=['#tools/freetype/freetype/include'])
+
+ if (env["target"]=="release"):
+
+ env.Append(CCFLAGS=['/O2'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
+
+ elif (env["target"]=="test"):
+
+ env.Append(CCFLAGS=['/O2','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+
+ elif (env["target"]=="debug"):
+
+ env.Append(CCFLAGS=['/Zi','/DDEBUG_ENABLED','/DD3D_DEBUG_INFO','/O1'])
+ env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
+
+ elif (env["target"]=="profile"):
+
+ env.Append(CCFLAGS=['-g','-pg'])
+ env.Append(LINKFLAGS=['-pg'])
+
+ env.Append(CCFLAGS=['/MT','/Gd','/GR','/nologo'])
+ env.Append(CXXFLAGS=['/TP'])
+ env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
+ env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"])
+ env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
+ env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
+ env.Append(CCFLAGS=['/DWIN32'])
+ env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
+
+ #env.Append(CCFLAGS=['/DLEGACYGL_ENABLED'])
+ env.Append(CCFLAGS=['/DGLES_ENABLED'])
+ #env.Append(CCFLAGS=['/DGLES1_ENABLED'])
+ env.Append(CCFLAGS=['/DGLEW_ENABLED'])
+ env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32','wsock32'])
+ env.Append(LINKFLAGS=['/DEBUG'])
+
+ env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
+ if (os.getenv("DXSDK_DIR")):
+ DIRECTX_PATH=os.getenv("DXSDK_DIR")
+ else:
+ DIRECTX_PATH="C:/Program Files/Microsoft DirectX SDK (March 2009)"
+
+ if (os.getenv("VCINSTALLDIR")):
+ VC_PATH=os.getenv("VCINSTALLDIR")
+ else:
+ VC_PATH=""
+
+ env.Append(CCFLAGS=["/I"+VC_PATH+"/Include"])
+ env.Append(LIBPATH=[VC_PATH+"/Lib"])
+ env.Append(CCFLAGS=["/I"+DIRECTX_PATH+"/Include"])
+ env.Append(LIBPATH=[DIRECTX_PATH+"/Lib/x86"])
+ env['ENV'] = os.environ;
+ else:
+ #build using mingw
+ if (os.name=="nt"):
+ env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes
+
+ mingw_prefix=""
+
+ if (env["force_32_bits"]!="no"):
+ env['OBJSUFFIX'] = ".32"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = ".32"+env['LIBSUFFIX']
+ env.Append(CCFLAGS=['-m32'])
+ env.Append(LINKFLAGS=['-m32'])
+
+
+
+
+ if (env["force_64_bits"]!="no"):
+ mingw_prefix=env["mingw_prefix_64"];
+ env['OBJSUFFIX'] = ".64"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = ".64"+env['LIBSUFFIX']
+ env.Append(LINKFLAGS=['-static'])
+ else:
+ mingw_prefix=env["mingw_prefix"];
+
+ if (env["target"]=="release"):
+
+ env.Append(CCFLAGS=['-O3','-ffast-math','-fomit-frame-pointer','-msse2'])
+ env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
+ elif (env["target"]=="release_debug"):
+
+ env.Append(CCFLAGS=['-O2','-DDEBUG_ENABLED'])
+ env['OBJSUFFIX'] = "_optd"+env['OBJSUFFIX']
+ env['LIBSUFFIX'] = "_optd"+env['LIBSUFFIX']
+
+ elif (env["target"]=="debug"):
+
+ env.Append(CCFLAGS=['-g', '-Wall','-DDEBUG_ENABLED'])
+ elif (env["target"]=="release_tools"):
+
+ env.Append(CCFLAGS=['-O2','-Wall','-DDEBUG_ENABLED'])
+
+
+ if (env["freetype"]!="no"):
+ env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
+ env.Append(CPPPATH=['#tools/freetype'])
+ env.Append(CPPPATH=['#tools/freetype/freetype/include'])
+
+ env["CC"]=mingw_prefix+"gcc"
+ env['AS']=mingw_prefix+"as"
+ env['CXX'] = mingw_prefix+"g++"
+ env['AR'] = mingw_prefix+"ar"
+ env['RANLIB'] = mingw_prefix+"ranlib"
+ env['LD'] = mingw_prefix+"g++"
+
+ #env['CC'] = "winegcc"
+ #env['CXX'] = "wineg++"
+
+ env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
+ env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
+ env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLES1_ENABLED','-DGLEW_ENABLED'])
+ env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','wsock32','kernel32'])
+ #'d3dx9d'
+ env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
+ env.Append(LINKFLAGS=['-g'])
+
+ import methods
+ env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+ env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
+ env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } )
+
+
+
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp new file mode 100644 index 0000000000..952f51fdd4 --- /dev/null +++ b/platform/windows/export/export.cpp @@ -0,0 +1,24 @@ +#include "export.h" +#include "platform/windows/logo.h" +#include "tools/editor/editor_import_export.h" + +void register_windows_exporter() { + + Image img(_windows_logo); + Ref<ImageTexture> logo = memnew( ImageTexture ); + logo->create_from_image(img); + + { + Ref<EditorExportPlatformPC> exporter = Ref<EditorExportPlatformPC>( memnew(EditorExportPlatformPC) ); + exporter->set_binary_extension("exe"); + exporter->set_release_binary32("windows_32_release.exe"); + exporter->set_debug_binary32("windows_32_debug.exe"); + exporter->set_release_binary64("windows_64_release.exe"); + exporter->set_debug_binary64("windows_64_debug.exe"); + exporter->set_name("Windows Desktop"); + exporter->set_logo(logo); + EditorImportExport::get_singleton()->add_export_platform(exporter); + } + + +} diff --git a/platform/windows/export/export.h b/platform/windows/export/export.h new file mode 100644 index 0000000000..de3dc3fa50 --- /dev/null +++ b/platform/windows/export/export.h @@ -0,0 +1,3 @@ + +void register_windows_exporter(); + diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_win.cpp new file mode 100644 index 0000000000..2999a9beae --- /dev/null +++ b/platform/windows/godot_win.cpp @@ -0,0 +1,207 @@ +/*************************************************************************/ +/* godot_win.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "os_windows.h" +#include "main/main.h" +#include <stdio.h> + +PCHAR* + CommandLineToArgvA( + PCHAR CmdLine, + int* _argc + ) + { + PCHAR* argv; + PCHAR _argv; + ULONG len; + ULONG argc; + CHAR a; + ULONG i, j; + + BOOLEAN in_QM; + BOOLEAN in_TEXT; + BOOLEAN in_SPACE; + + len = strlen(CmdLine); + i = ((len+2)/2)*sizeof(PVOID) + sizeof(PVOID); + + argv = (PCHAR*)GlobalAlloc(GMEM_FIXED, + i + (len+2)*sizeof(CHAR)); + + _argv = (PCHAR)(((PUCHAR)argv)+i); + + argc = 0; + argv[argc] = _argv; + in_QM = FALSE; + in_TEXT = FALSE; + in_SPACE = TRUE; + i = 0; + j = 0; + + while( (a = CmdLine[i]) ) { + if(in_QM) { + if(a == '\"') { + in_QM = FALSE; + } else { + _argv[j] = a; + j++; + } + } else { + switch(a) { + case '\"': + in_QM = TRUE; + in_TEXT = TRUE; + if(in_SPACE) { + argv[argc] = _argv+j; + argc++; + } + in_SPACE = FALSE; + break; + case ' ': + case '\t': + case '\n': + case '\r': + if(in_TEXT) { + _argv[j] = '\0'; + j++; + } + in_TEXT = FALSE; + in_SPACE = TRUE; + break; + default: + in_TEXT = TRUE; + if(in_SPACE) { + argv[argc] = _argv+j; + argc++; + } + _argv[j] = a; + j++; + in_SPACE = FALSE; + break; + } + } + i++; + } + _argv[j] = '\0'; + argv[argc] = NULL; + + (*_argc) = argc; + return argv; + } + +int main(int argc, char** argv) { + + OS_Windows os(NULL); + + Main::setup(argv[0], argc - 1, &argv[1]); + if (Main::start()) + os.run(); + Main::cleanup(); + + return os.get_exit_code(); +}; + +HINSTANCE godot_hinstance = NULL; + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + + int argc; + char** argv; + + char* arg; + int index; + int result; + + // count the arguments + + argc = 1; + arg = lpCmdLine; + + while (arg[0] != 0) { + + while (arg[0] != 0 && arg[0] == ' ') { + arg++; + } + + if (arg[0] != 0) { + + argc++; + + while (arg[0] != 0 && arg[0] != ' ') { + arg++; + } + + } + + } + + // tokenize the arguments + + argv = (char**)malloc(argc * sizeof(char*)); + + arg = lpCmdLine; + index = 1; + + while (arg[0] != 0) { + + while (arg[0] != 0 && arg[0] == ' ') { + arg++; + } + + if (arg[0] != 0) { + + argv[index] = arg; + index++; + + while (arg[0] != 0 && arg[0] != ' ') { + arg++; + } + + if (arg[0] != 0) { + arg[0] = 0; + arg++; + } + + } + + } + + // put the program name into argv[0] + + char filename[_MAX_PATH]; + + GetModuleFileName(NULL, filename, _MAX_PATH); + argv[0] = filename; + + // call the user specified main function + + result = main(argc, argv); + + free(argv); + return result; +} diff --git a/platform/windows/key_mapping_win.cpp b/platform/windows/key_mapping_win.cpp new file mode 100644 index 0000000000..bdf3b2a92f --- /dev/null +++ b/platform/windows/key_mapping_win.cpp @@ -0,0 +1,256 @@ +/*************************************************************************/ +/* key_mapping_win.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#define WINVER 0x0500 +#include "key_mapping_win.h" +#include <stdio.h> + +struct _WinTranslatePair { + + unsigned int keysym; + unsigned int keycode; +}; + + +static _WinTranslatePair _vk_to_keycode[]={ + +{ KEY_BACKSPACE, VK_BACK },// (0x08) // backspace +{ KEY_TAB, VK_TAB },//(0x09) + +//VK_CLEAR (0x0C) + +{ KEY_RETURN, VK_RETURN },//(0x0D) + +{ KEY_SHIFT, VK_SHIFT },//(0x10) + +{ KEY_CONTROL, VK_CONTROL },//(0x11) + +{ KEY_MENU, VK_MENU },//(0x12) + +{ KEY_PAUSE, VK_PAUSE },//(0x13) + +{ KEY_CAPSLOCK, VK_CAPITAL },//(0x14) + +{ KEY_ESCAPE, VK_ESCAPE },//(0x1B) + +{ KEY_SPACE, VK_SPACE },//(0x20) + +{ KEY_PAGEUP,VK_PRIOR },//(0x21) + +{ KEY_PAGEDOWN, VK_NEXT },//(0x22) + +{ KEY_END, VK_END },//(0x23) + +{ KEY_HOME, VK_HOME },//(0x24) + +{ KEY_LEFT, VK_LEFT },//(0x25) + +{ KEY_UP, VK_UP },//(0x26) + +{ KEY_RIGHT,VK_RIGHT },//(0x27) + +{ KEY_DOWN, VK_DOWN},// (0x28) + +//VK_SELECT (0x29) + +{ KEY_PRINT, VK_PRINT},// (0x2A) + +//VK_EXECUTE (0x2B) + +{ KEY_PRINT, VK_SNAPSHOT},// (0x2C) + +{ KEY_INSERT, VK_INSERT},// (0x2D) + +{ KEY_DELETE, VK_DELETE},// (0x2E) + +{ KEY_HELP, VK_HELP},// (0x2F) + + +{ KEY_0, (0x30) },////0 key +{ KEY_1, (0x31) },////1 key +{ KEY_2, (0x32) },////2 key +{ KEY_3, (0x33) },////3 key +{ KEY_4, (0x34) },////4 key +{ KEY_5, (0x35) },////5 key +{ KEY_6, (0x36) },////6 key +{ KEY_7, (0x37) },////7 key +{ KEY_8, (0x38) },////8 key +{ KEY_9, (0x39) },////9 key +{ KEY_A, (0x41) },////A key +{ KEY_B, (0x42) },////B key +{ KEY_C, (0x43) },////C key +{ KEY_D, (0x44) },////D key +{ KEY_E, (0x45) },////E key +{ KEY_F, (0x46) },////F key +{ KEY_G, (0x47) },////G key +{ KEY_H, (0x48) },////H key +{ KEY_I, (0x49) },////I key +{ KEY_J, (0x4A) },////J key +{ KEY_K, (0x4B) },////K key +{ KEY_L, (0x4C) },////L key +{ KEY_M, (0x4D) },////M key +{ KEY_N, (0x4E) },////N key +{ KEY_O, (0x4F) },////O key +{ KEY_P, (0x50) },////P key +{ KEY_Q, (0x51) },////Q key +{ KEY_R, (0x52) },////R key +{ KEY_S, (0x53) },////S key +{ KEY_T, (0x54) },////T key +{ KEY_U, (0x55) },////U key +{ KEY_V, (0x56) },////V key +{ KEY_W, (0x57) },////W key +{ KEY_X, (0x58) },////X key +{ KEY_Y, (0x59) },////Y key +{ KEY_Z, (0x5A) },////Z key + +{ KEY_MASK_META, VK_LWIN },//(0x5B) +{ KEY_MASK_META, VK_RWIN },//(0x5C) +//VK_APPS (0x5D) +{ KEY_STANDBY,VK_SLEEP },//(0x5F) +{ KEY_KP_0,VK_NUMPAD0 },//(0x60) +{ KEY_KP_1,VK_NUMPAD1 },//(0x61) +{ KEY_KP_2,VK_NUMPAD2 },//(0x62) +{ KEY_KP_3,VK_NUMPAD3 },//(0x63) +{ KEY_KP_4,VK_NUMPAD4 },//(0x64) +{ KEY_KP_5,VK_NUMPAD5 },//(0x65) +{ KEY_KP_6,VK_NUMPAD6 },//(0x66) +{ KEY_KP_7,VK_NUMPAD7 },//(0x67) +{ KEY_KP_8,VK_NUMPAD8 },//(0x68) +{ KEY_KP_9,VK_NUMPAD9 },//(0x69) +{ KEY_KP_MULTIPLY,VK_MULTIPLY},// (0x6A) +{ KEY_KP_ADD,VK_ADD},// (0x6B) +//VK_SEPARATOR (0x6C) +{ KEY_KP_SUBSTRACT,VK_SUBTRACT},// (0x6D) +{ KEY_KP_PERIOD,VK_DECIMAL},// (0x6E) +{ KEY_KP_DIVIDE,VK_DIVIDE},// (0x6F) +{ KEY_F1,VK_F1},// (0x70) +{ KEY_F2,VK_F2},// (0x71) +{ KEY_F3,VK_F3},// (0x72) +{ KEY_F4,VK_F4},// (0x73) +{ KEY_F5,VK_F5},// (0x74) +{ KEY_F6,VK_F6},// (0x75) +{ KEY_F7,VK_F7},// (0x76) +{ KEY_F8,VK_F8},// (0x77) +{ KEY_F9,VK_F9},// (0x78) +{ KEY_F10,VK_F10},// (0x79) +{ KEY_F11,VK_F11},// (0x7A) +{ KEY_F12,VK_F12},// (0x7B) +{ KEY_F13,VK_F13},// (0x7C) +{ KEY_F14,VK_F14},// (0x7D) +{ KEY_F15,VK_F15},// (0x7E) +{ KEY_F16,VK_F16},// (0x7F) +{ KEY_NUMLOCK,VK_NUMLOCK},// (0x90) +{ KEY_SCROLLLOCK,VK_SCROLL},// (0x91) +{ KEY_SHIFT,VK_LSHIFT},// (0xA0) +{ KEY_SHIFT,VK_RSHIFT},// (0xA1) +{ KEY_CONTROL,VK_LCONTROL},// (0xA2) +{ KEY_CONTROL,VK_RCONTROL},// (0xA3) +{ KEY_MENU,VK_LMENU},// (0xA4) +{ KEY_MENU,VK_RMENU},// (0xA5) + + +{ KEY_BACK,VK_BROWSER_BACK},// (0xA6) + +{ KEY_FORWARD,VK_BROWSER_FORWARD},// (0xA7) + +{ KEY_REFRESH,VK_BROWSER_REFRESH},// (0xA8) + +{ KEY_STOP,VK_BROWSER_STOP},// (0xA9) + +{ KEY_SEARCH,VK_BROWSER_SEARCH},// (0xAA) + +{ KEY_FAVORITES, VK_BROWSER_FAVORITES},// (0xAB) + +{ KEY_HOMEPAGE,VK_BROWSER_HOME},// (0xAC) + +{ KEY_VOLUMEMUTE,VK_VOLUME_MUTE},// (0xAD) + +{ KEY_VOLUMEDOWN,VK_VOLUME_DOWN},// (0xAE) + +{ KEY_VOLUMEUP,VK_VOLUME_UP},// (0xAF) + + +{ KEY_MEDIANEXT,VK_MEDIA_NEXT_TRACK},// (0xB0) + +{ KEY_MEDIAPREVIOUS,VK_MEDIA_PREV_TRACK},// (0xB1) + +{ KEY_MEDIASTOP,VK_MEDIA_STOP},// (0xB2) + +//VK_MEDIA_PLAY_PAUSE (0xB3) + +{ KEY_LAUNCHMAIL, VK_LAUNCH_MAIL},// (0xB4) + +{ KEY_LAUNCHMEDIA,VK_LAUNCH_MEDIA_SELECT},// (0xB5) + +{ KEY_LAUNCH0,VK_LAUNCH_APP1},// (0xB6) + +{ KEY_LAUNCH1,VK_LAUNCH_APP2},// (0xB7) + +{ KEY_SEMICOLON,VK_OEM_1},// (0xBA) + + +{ KEY_EQUAL, VK_OEM_PLUS},// (0xBB) // Windows 2000/XP: For any country/region, the '+' key +{ KEY_COLON,VK_OEM_COMMA},// (0xBC) // Windows 2000/XP: For any country/region, the ',' key +{ KEY_MINUS,VK_OEM_MINUS},// (0xBD) // Windows 2000/XP: For any country/region, the '-' key +{ KEY_PERIOD,VK_OEM_PERIOD},// (0xBE) // Windows 2000/XP: For any country/region, the '.' key +{ KEY_SLASH,VK_OEM_2},// (0xBF) //Windows 2000/XP: For the US standard keyboard, the '/?' key + +{KEY_QUOTELEFT, VK_OEM_3},// (0xC0) +{KEY_BRACELEFT,VK_OEM_4},// (0xDB) +{KEY_BACKSLASH,VK_OEM_5},// (0xDC) +{KEY_BRACERIGHT,VK_OEM_6},// (0xDD) +{KEY_APOSTROPHE, VK_OEM_7},// (0xDE) +/* +{VK_OEM_8 (0xDF) +{VK_OEM_102 (0xE2) // Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard +*/ +//{ KEY_PLAY, VK_PLAY},// (0xFA) + +{KEY_UNKNOWN, 0} }; + +/* +VK_ZOOM (0xFB) +VK_NONAME (0xFC) +VK_PA1 (0xFD) +VK_OEM_CLEAR (0xFE) +*/ + +unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) { + + for(int i=0;_vk_to_keycode[i].keysym!=KEY_UNKNOWN;i++) { + + if (_vk_to_keycode[i].keycode==p_code) { + //printf("outcode: %x\n",_vk_to_keycode[i].keysym); + + return _vk_to_keycode[i].keysym; + } + } + + + return KEY_UNKNOWN; +} diff --git a/platform/windows/key_mapping_win.h b/platform/windows/key_mapping_win.h new file mode 100644 index 0000000000..3e351675b0 --- /dev/null +++ b/platform/windows/key_mapping_win.h @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* key_mapping_win.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef KEY_MAPPING_WINDOWS_H
+#define KEY_MAPPING_WINDOWS_H
+
+
+#include "os/keyboard.h"
+
+#include <windows.h>
+
+#include <winuser.h>
+
+
+class KeyMappingWindows {
+
+ KeyMappingWindows() {};
+public:
+
+ static unsigned int get_keysym(unsigned int p_code);
+
+};
+
+
+
+#endif
diff --git a/platform/windows/lang_table.h b/platform/windows/lang_table.h new file mode 100644 index 0000000000..83f3fb52fd --- /dev/null +++ b/platform/windows/lang_table.h @@ -0,0 +1,190 @@ +/*************************************************************************/ +/* lang_table.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef LANG_TABLE_H +#define LANG_TABLE_H + +//#include <windows.h> + +struct _WinLocale { + const char *locale; + int main_lang; + int sublang; +}; + +static const _WinLocale _win_locales[]={ +{"ar", LANG_ARABIC,SUBLANG_NEUTRAL}, +{"ar_AE", LANG_ARABIC,SUBLANG_ARABIC_UAE}, +{"ar_BH", LANG_ARABIC,SUBLANG_ARABIC_BAHRAIN}, +{"ar_DZ", LANG_ARABIC,SUBLANG_ARABIC_ALGERIA}, +{"ar_EG", LANG_ARABIC,SUBLANG_ARABIC_EGYPT}, +{"ar_IQ", LANG_ARABIC,SUBLANG_ARABIC_IRAQ}, +{"ar_JO", LANG_ARABIC,SUBLANG_ARABIC_JORDAN}, +{"ar_KW", LANG_ARABIC,SUBLANG_ARABIC_KUWAIT}, +{"ar_LB", LANG_ARABIC,SUBLANG_ARABIC_LEBANON}, +{"ar_LY", LANG_ARABIC,SUBLANG_ARABIC_LIBYA}, +{"ar_MA", LANG_ARABIC,SUBLANG_ARABIC_MOROCCO}, +{"ar_OM", LANG_ARABIC,SUBLANG_ARABIC_OMAN}, +{"ar_QA", LANG_ARABIC,SUBLANG_ARABIC_QATAR}, +{"ar_SA", LANG_ARABIC,SUBLANG_ARABIC_SAUDI_ARABIA}, +//no sudan +{"ar_SY", LANG_ARABIC,SUBLANG_ARABIC_SYRIA}, +{"ar_TN", LANG_ARABIC,SUBLANG_ARABIC_TUNISIA}, +{"ar_YE", LANG_ARABIC,SUBLANG_ARABIC_YEMEN}, +{"be", LANG_BELARUSIAN,SUBLANG_NEUTRAL}, +{"be_BY", LANG_BELARUSIAN,SUBLANG_BELARUSIAN_BELARUS}, +{"bg", LANG_BULGARIAN,SUBLANG_NEUTRAL}, +{"bg_BG", LANG_BULGARIAN,SUBLANG_BULGARIAN_BULGARIA}, +{"ca", LANG_CATALAN,SUBLANG_NEUTRAL}, +{"ca_ES", LANG_CATALAN,SUBLANG_CATALAN_CATALAN}, +{"cs", LANG_CZECH,SUBLANG_NEUTRAL}, +{"cs_CZ", LANG_CZECH,SUBLANG_CZECH_CZECH_REPUBLIC}, +{"da", LANG_DANISH,SUBLANG_NEUTRAL}, +{"da_DK", LANG_DANISH,SUBLANG_DANISH_DENMARK}, +{"de", LANG_GERMAN,SUBLANG_NEUTRAL}, +{"de_AT", LANG_GERMAN,SUBLANG_GERMAN_AUSTRIAN}, +{"de_CH", LANG_GERMAN,SUBLANG_GERMAN_SWISS}, +{"de_DE", LANG_GERMAN,SUBLANG_GERMAN}, +{"de_LU", LANG_GERMAN,SUBLANG_GERMAN_LUXEMBOURG}, +{"el", LANG_GREEK,SUBLANG_NEUTRAL}, +{"el_GR", LANG_GREEK,SUBLANG_GREEK_GREECE}, +//{"en_029", LANG_ENGLISH,SUBLANG_ENGLISH_CARIBBEAN}, +{"en", LANG_ENGLISH,SUBLANG_NEUTRAL}, +{"en_AU", LANG_ENGLISH,SUBLANG_ENGLISH_AUS}, +{"en_CA", LANG_ENGLISH,SUBLANG_ENGLISH_CAN}, +{"en_GB", LANG_ENGLISH,SUBLANG_ENGLISH_UK}, +//{"en_IE", LANG_ENGLISH,SUBLANG_ENGLISH_IRELAND}, +{"en_IN", LANG_ENGLISH,SUBLANG_ENGLISH_INDIA}, +//MT +{"en_NZ", LANG_ENGLISH,SUBLANG_ENGLISH_NZ}, +{"en_PH", LANG_ENGLISH,SUBLANG_ENGLISH_PHILIPPINES}, +{"en_SG", LANG_ENGLISH,SUBLANG_ENGLISH_SINGAPORE}, +{"en_US", LANG_ENGLISH,SUBLANG_ENGLISH_US}, +{"en_ZA", LANG_ENGLISH,SUBLANG_ENGLISH_SOUTH_AFRICA}, +{"es", LANG_SPANISH,SUBLANG_NEUTRAL}, +{"es_AR", LANG_SPANISH,SUBLANG_SPANISH_ARGENTINA}, +{"es_BO", LANG_SPANISH,SUBLANG_SPANISH_BOLIVIA}, +{"es_CL", LANG_SPANISH,SUBLANG_SPANISH_CHILE}, +{"es_CO", LANG_SPANISH,SUBLANG_SPANISH_COLOMBIA}, +{"es_CR", LANG_SPANISH,SUBLANG_SPANISH_COSTA_RICA}, +{"es_DO", LANG_SPANISH,SUBLANG_SPANISH_DOMINICAN_REPUBLIC}, +{"es_EC", LANG_SPANISH,SUBLANG_SPANISH_ECUADOR}, +{"es_ES", LANG_SPANISH,SUBLANG_SPANISH}, +{"es_GT", LANG_SPANISH,SUBLANG_SPANISH_GUATEMALA}, +{"es_HN", LANG_SPANISH,SUBLANG_SPANISH_HONDURAS}, +{"es_MX", LANG_SPANISH,SUBLANG_SPANISH_MEXICAN}, +{"es_NI", LANG_SPANISH,SUBLANG_SPANISH_NICARAGUA}, +{"es_PA", LANG_SPANISH,SUBLANG_SPANISH_PANAMA}, +{"es_PE", LANG_SPANISH,SUBLANG_SPANISH_PERU}, +{"es_PR", LANG_SPANISH,SUBLANG_SPANISH_PUERTO_RICO}, +{"es_PY", LANG_SPANISH,SUBLANG_SPANISH_PARAGUAY}, +{"es_SV", LANG_SPANISH,SUBLANG_SPANISH_EL_SALVADOR}, +{"es_US", LANG_SPANISH,SUBLANG_SPANISH_US}, +{"es_UY", LANG_SPANISH,SUBLANG_SPANISH_URUGUAY}, +{"es_VE", LANG_SPANISH,SUBLANG_SPANISH_VENEZUELA}, +{"et", LANG_ESTONIAN,SUBLANG_NEUTRAL}, +{"et_EE", LANG_ESTONIAN,SUBLANG_ESTONIAN_ESTONIA}, +{"fi", LANG_FINNISH,SUBLANG_NEUTRAL}, +{"fi_FI", LANG_FINNISH,SUBLANG_FINNISH_FINLAND}, +{"fr", LANG_FRENCH,SUBLANG_NEUTRAL}, +{"fr_BE", LANG_FRENCH,SUBLANG_FRENCH_BELGIAN}, +{"fr_CA", LANG_FRENCH,SUBLANG_FRENCH_CANADIAN}, +{"fr_CH", LANG_FRENCH,SUBLANG_FRENCH_SWISS}, +{"fr_FR", LANG_FRENCH,SUBLANG_FRENCH}, +{"fr_LU", LANG_FRENCH,SUBLANG_FRENCH_LUXEMBOURG}, +{"ga", LANG_IRISH,SUBLANG_NEUTRAL}, +{"ga_IE", LANG_IRISH,SUBLANG_IRISH_IRELAND}, +{"hi", LANG_HINDI,SUBLANG_NEUTRAL}, +{"hi_IN", LANG_HINDI,SUBLANG_HINDI_INDIA}, +{"hr", LANG_CROATIAN,SUBLANG_NEUTRAL}, +{"hr_HR", LANG_CROATIAN,SUBLANG_CROATIAN_CROATIA}, +{"hu", LANG_HUNGARIAN,SUBLANG_NEUTRAL}, +{"hu_HU", LANG_HUNGARIAN,SUBLANG_HUNGARIAN_HUNGARY}, +{"in", LANG_ARMENIAN,SUBLANG_NEUTRAL}, +{"in_ID", LANG_INDONESIAN,SUBLANG_INDONESIAN_INDONESIA}, +{"is", LANG_ICELANDIC,SUBLANG_NEUTRAL}, +{"is_IS", LANG_ICELANDIC,SUBLANG_ICELANDIC_ICELAND}, +{"it", LANG_ITALIAN,SUBLANG_NEUTRAL}, +{"it_CH", LANG_ITALIAN,SUBLANG_ITALIAN_SWISS}, +{"it_IT", LANG_ITALIAN,SUBLANG_ITALIAN}, +{"iw", LANG_HEBREW,SUBLANG_NEUTRAL}, +{"iw_IL", LANG_HEBREW,SUBLANG_HEBREW_ISRAEL}, +{"ja", LANG_JAPANESE,SUBLANG_NEUTRAL}, +{"ja_JP", LANG_JAPANESE,SUBLANG_JAPANESE_JAPAN}, +{"ko", LANG_KOREAN,SUBLANG_NEUTRAL}, +{"ko_KR", LANG_KOREAN,SUBLANG_KOREAN}, +{"lt", LANG_LITHUANIAN,SUBLANG_NEUTRAL}, +//{"lt_LT", LANG_LITHUANIAN,SUBLANG_LITHUANIAN_LITHUANIA}, +{"lv", LANG_LATVIAN,SUBLANG_NEUTRAL}, +{"lv_LV", LANG_LATVIAN,SUBLANG_LATVIAN_LATVIA}, +{"mk", LANG_MACEDONIAN,SUBLANG_NEUTRAL}, +{"mk_MK", LANG_MACEDONIAN,SUBLANG_MACEDONIAN_MACEDONIA}, +{"ms", LANG_MALAY,SUBLANG_NEUTRAL}, +{"ms_MY", LANG_MALAY,SUBLANG_MALAY_MALAYSIA}, +{"mt", LANG_MALTESE,SUBLANG_NEUTRAL}, +{"mt_MT", LANG_MALTESE,SUBLANG_MALTESE_MALTA}, +{"nl", LANG_DUTCH,SUBLANG_NEUTRAL}, +{"nl_BE", LANG_DUTCH,SUBLANG_DUTCH_BELGIAN}, +{"nl_NL", LANG_DUTCH,SUBLANG_DUTCH}, +{"no", LANG_NORWEGIAN,SUBLANG_NEUTRAL}, +{"no_NO", LANG_NORWEGIAN,SUBLANG_NORWEGIAN_BOKMAL}, +{"no_NO_NY", LANG_NORWEGIAN,SUBLANG_NORWEGIAN_NYNORSK}, +{"pl", LANG_POLISH,SUBLANG_NEUTRAL}, +{"pl_PL", LANG_POLISH,SUBLANG_POLISH_POLAND}, +{"pt", LANG_PORTUGUESE,SUBLANG_NEUTRAL}, +{"pt_BR", LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN}, +{"pt_PT", LANG_PORTUGUESE,SUBLANG_PORTUGUESE}, +{"ro", LANG_ROMANIAN,SUBLANG_NEUTRAL}, +{"ro_RO", LANG_ROMANIAN,SUBLANG_ROMANIAN_ROMANIA}, +{"ru", LANG_RUSSIAN,SUBLANG_NEUTRAL}, +{"ru_RU", LANG_RUSSIAN,SUBLANG_RUSSIAN_RUSSIA}, +{"sk", LANG_SLOVAK,SUBLANG_NEUTRAL}, +{"sk_SK", LANG_SLOVAK,SUBLANG_SLOVAK_SLOVAKIA}, +{"sl", LANG_SLOVENIAN,SUBLANG_NEUTRAL}, +{"sl_SI", LANG_SLOVENIAN,SUBLANG_SLOVENIAN_SLOVENIA}, +{"sq", LANG_ALBANIAN,SUBLANG_NEUTRAL}, +{"sq_AL", LANG_ALBANIAN,SUBLANG_ALBANIAN_ALBANIA}, +{"sr", LANG_SERBIAN_NEUTRAL,SUBLANG_NEUTRAL}, +{"sv", LANG_SWEDISH,SUBLANG_NEUTRAL}, +{"sv_SE", LANG_SWEDISH,SUBLANG_SWEDISH}, +{"th", LANG_THAI,SUBLANG_NEUTRAL}, +{"th_TH", LANG_THAI,SUBLANG_THAI_THAILAND}, +{"tr", LANG_TURKISH,SUBLANG_NEUTRAL}, +{"tr_TR", LANG_TURKISH,SUBLANG_TURKISH_TURKEY}, +{"uk", LANG_UKRAINIAN,SUBLANG_NEUTRAL}, +{"uk_UA", LANG_UKRAINIAN,SUBLANG_UKRAINIAN_UKRAINE}, +{"vi", LANG_VIETNAMESE,SUBLANG_NEUTRAL}, +{"vi_VN", LANG_VIETNAMESE,SUBLANG_VIETNAMESE_VIETNAM}, +{"zh", LANG_CHINESE,SUBLANG_NEUTRAL}, +{"zh_CN", LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED}, +{"zh_HK", LANG_CHINESE,SUBLANG_CHINESE_HONGKONG}, +{"zh_SG", LANG_CHINESE,SUBLANG_CHINESE_SINGAPORE}, +{0, 0,0}, +}; + +#endif // LANG_TABLE_H diff --git a/platform/windows/logo.png b/platform/windows/logo.png Binary files differnew file mode 100644 index 0000000000..a27e14dde8 --- /dev/null +++ b/platform/windows/logo.png diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp new file mode 100644 index 0000000000..efeb813a2d --- /dev/null +++ b/platform/windows/os_windows.cpp @@ -0,0 +1,1732 @@ +/*************************************************************************/ +/* os_windows.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "drivers/gles2/rasterizer_gles2.h" +#include "drivers/gles1/rasterizer_gles1.h" +#include "os_windows.h" +#include "drivers/nedmalloc/memory_pool_static_nedmalloc.h" +#include "drivers/unix/memory_pool_static_malloc.h" +#include "os/memory_pool_dynamic_static.h" +#include "drivers/windows/thread_windows.h" +#include "drivers/windows/semaphore_windows.h" +#include "drivers/windows/mutex_windows.h" +#include "main/main.h" +#include "drivers/windows/file_access_windows.h" +#include "drivers/windows/dir_access_windows.h" + + +#include "servers/visual/visual_server_raster.h" +#include "servers/audio/audio_server_sw.h" +#include "servers/visual/visual_server_wrap_mt.h" + +#include "tcp_server_winsock.h" +#include "stream_peer_winsock.h" +#include "os/pc_joystick_map.h" +#include "lang_table.h" +#include "os/memory_pool_dynamic_prealloc.h" +#include "globals.h" +#include "io/marshalls.h" +static const WORD MAX_CONSOLE_LINES = 1500; + +//#define STDOUT_FILE + +extern HINSTANCE godot_hinstance; + +void RedirectIOToConsole() { + + int hConHandle; + + intptr_t lStdHandle; + + CONSOLE_SCREEN_BUFFER_INFO coninfo; + + FILE *fp; + + // allocate a console for this app + + AllocConsole(); + + // set the screen buffer to be big enough to let us scroll text + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), + + &coninfo); + + coninfo.dwSize.Y = MAX_CONSOLE_LINES; + + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), + + coninfo.dwSize); + + // redirect unbuffered STDOUT to the console + + lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE); + + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + + fp = _fdopen( hConHandle, "w" ); + + *stdout = *fp; + + setvbuf( stdout, NULL, _IONBF, 0 ); + + // redirect unbuffered STDIN to the console + + lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE); + + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + + fp = _fdopen( hConHandle, "r" ); + + *stdin = *fp; + + setvbuf( stdin, NULL, _IONBF, 0 ); + + // redirect unbuffered STDERR to the console + + lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE); + + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + + fp = _fdopen( hConHandle, "w" ); + + *stderr = *fp; + + setvbuf( stderr, NULL, _IONBF, 0 ); + + // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog + + // point to console as well +} + +int OS_Windows::get_video_driver_count() const { + + return 2; +} +const char * OS_Windows::get_video_driver_name(int p_driver) const { + + return p_driver==0?"GLES2":"GLES1"; +} + +OS::VideoMode OS_Windows::get_default_video_mode() const { + + return VideoMode(800,600,false); +} + +int OS_Windows::get_audio_driver_count() const { + + return AudioDriverManagerSW::get_driver_count(); +} +const char * OS_Windows::get_audio_driver_name(int p_driver) const { + + AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver); + ERR_FAIL_COND_V( !driver, "" ); + return AudioDriverManagerSW::get_driver(p_driver)->get_name(); +} + +static MemoryPoolStatic *mempool_static=NULL; +static MemoryPoolDynamic *mempool_dynamic=NULL; + +void OS_Windows::initialize_core() { + + + last_button_state=0; + + //RedirectIOToConsole(); + + ThreadWindows::make_default(); + SemaphoreWindows::make_default(); + MutexWindows::make_default(); + + FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES); + FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA); + FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM); + //FileAccessBufferedFA<FileAccessWindows>::make_default(); + DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA); + DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM); + + TCPServerWinsock::make_default(); + StreamPeerWinsock::make_default(); + + mempool_static = new MemoryPoolStaticMalloc; +#if 1 + mempool_dynamic = memnew( MemoryPoolDynamicStatic ); +#else +#define DYNPOOL_SIZE 4*1024*1024 + void * buffer = malloc( DYNPOOL_SIZE ); + mempool_dynamic = memnew( MemoryPoolDynamicPrealloc(buffer,DYNPOOL_SIZE) ); + +#endif + + // We need to know how often the clock is updated + if( !QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second) ) + ticks_per_second = 1000; + // If timeAtGameStart is 0 then we get the time since + // the start of the computer when we call GetGameTime() + ticks_start = 0; + ticks_start = get_ticks_usec(); + + process_map = memnew((Map<ProcessID, ProcessInfo>)); + + IP_Unix::make_default(); + + cursor_shape=CURSOR_ARROW; + + +} + +bool OS_Windows::can_draw() const { + + return !minimized; +}; + + +LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { + + + switch (uMsg) // Check For Windows Messages + { + case WM_ACTIVATE: // Watch For Window Activate Message + { + minimized = HIWORD(wParam) != 0; + if (!main_loop) { + return 0; + }; + if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) { + + main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); + alt_mem=false; + control_mem=false; + shift_mem=false; + if (mouse_mode==MOUSE_MODE_CAPTURED) { + RECT clipRect; + GetClientRect(hWnd, &clipRect); + ClientToScreen(hWnd, (POINT*) &clipRect.left); + ClientToScreen(hWnd, (POINT*) &clipRect.right); + ClipCursor(&clipRect); + SetCapture(hWnd); + + } + } else { + main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); + alt_mem=false; + + }; + + return 0; // Return To The Message Loop + } + + case WM_PAINT: + + Main::force_redraw(); + break; + + case WM_SYSCOMMAND: // Intercept System Commands + { + switch (wParam) // Check System Calls + { + case SC_SCREENSAVE: // Screensaver Trying To Start? + case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? + return 0; // Prevent From Happening + case SC_KEYMENU: + if ((lParam>>16)<=0) + return 0; + } + break; // Exit + } + + case WM_CLOSE: // Did We Receive A Close Message? + { + if (main_loop) + main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST); + //force_quit=true; + return 0; // Jump Back + } + case WM_MOUSELEAVE: { + + old_invalid=true; + outside=true; + + } break; + case WM_MOUSEMOVE: { + + if (outside) { + + CursorShape c=cursor_shape; + cursor_shape=CURSOR_MAX; + set_cursor_shape(c); + outside=false; + + //Once-Off notification, must call again.... + TRACKMOUSEEVENT tme; + tme.cbSize=sizeof(TRACKMOUSEEVENT); + tme.dwFlags=TME_LEAVE; + tme.hwndTrack=hWnd; + tme.dwHoverTime=HOVER_DEFAULT; + TrackMouseEvent(&tme); + + } + InputEvent event; + event.type=InputEvent::MOUSE_MOTION; + event.ID=++last_id; + InputEventMouseMotion &mm=event.mouse_motion; + + mm.mod.control=(wParam&MK_CONTROL)!=0; + mm.mod.shift=(wParam&MK_SHIFT)!=0; + mm.mod.alt=alt_mem; + + mm.button_mask|=(wParam&MK_LBUTTON)?(1<<0):0; + mm.button_mask|=(wParam&MK_RBUTTON)?(1<<1):0; + mm.button_mask|=(wParam&MK_MBUTTON)?(1<<2):0; + last_button_state=mm.button_mask; + /*mm.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0; + mm.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/ + mm.x=GET_X_LPARAM(lParam); + mm.y=GET_Y_LPARAM(lParam); + + if (mouse_mode==MOUSE_MODE_CAPTURED) { + + Point2i c(video_mode.width/2,video_mode.height/2); + if (Point2i(mm.x,mm.y)==c) { + center=c; + return 0; + } + + Point2i ncenter(mm.x,mm.y); + mm.x = old_x + (mm.x-center.x); + mm.y = old_y + (mm.y-center.y); + center=ncenter; + POINT pos = { (int) c.x, (int) c.y }; + ClientToScreen(hWnd, &pos); + SetCursorPos(pos.x, pos.y); + + } + + input->set_mouse_pos(Point2(mm.x,mm.y)); + mm.speed_x=input->get_mouse_speed().x; + mm.speed_y=input->get_mouse_speed().y; + + if (old_invalid) { + + old_x=mm.x; + old_y=mm.y; + old_invalid=false; + } + + mm.relative_x=mm.x-old_x; + mm.relative_y=mm.y-old_y; + old_x=mm.x; + old_y=mm.y; + if (main_loop) + input->parse_input_event(event); + + + + } break; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSEWHEEL: + case WM_LBUTTONDBLCLK: + /*case WM_XBUTTONDOWN: + case WM_XBUTTONUP: */{ + + InputEvent event; + event.type=InputEvent::MOUSE_BUTTON; + event.ID=++last_id; + InputEventMouseButton &mb=event.mouse_button; + + switch (uMsg) { + case WM_LBUTTONDOWN: { + mb.pressed=true; + mb.button_index=1; + } break; + case WM_LBUTTONUP: { + mb.pressed=false; + mb.button_index=1; + } break; + case WM_MBUTTONDOWN: { + mb.pressed=true; + mb.button_index=3; + + } break; + case WM_MBUTTONUP: { + mb.pressed=false; + mb.button_index=3; + } break; + case WM_RBUTTONDOWN: { + mb.pressed=true; + mb.button_index=2; + } break; + case WM_RBUTTONUP: { + mb.pressed=false; + mb.button_index=2; + } break; + case WM_LBUTTONDBLCLK: { + + mb.pressed=true; + mb.button_index=1; + mb.doubleclick = true; + } break; + case WM_MOUSEWHEEL: { + + mb.pressed=true; + int motion = (short)HIWORD(wParam); + if (!motion) + return 0; + + + if (motion>0) + mb.button_index=4; + else + mb.button_index=5; + + + } break; + /* + case WM_XBUTTONDOWN: { + mb.pressed=true; + mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7; + } break; + case WM_XBUTTONUP: + mb.pressed=true; + mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7; + } break;*/ + default: { return 0; } + } + + + mb.mod.control=(wParam&MK_CONTROL)!=0; + mb.mod.shift=(wParam&MK_SHIFT)!=0; + mb.mod.alt=alt_mem; + //mb.mod.alt=(wParam&MK_MENU)!=0; + mb.button_mask|=(wParam&MK_LBUTTON)?(1<<0):0; + mb.button_mask|=(wParam&MK_RBUTTON)?(1<<1):0; + mb.button_mask|=(wParam&MK_MBUTTON)?(1<<2):0; + + last_button_state=mb.button_mask; + /* + mb.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0; + mb.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/ + mb.x=GET_X_LPARAM(lParam); + mb.y=GET_Y_LPARAM(lParam); + + if (mouse_mode==MOUSE_MODE_CAPTURED) { + + mb.x=old_x; + mb.y=old_y; + } + + mb.global_x=mb.x; + mb.global_y=mb.y; + + + if (uMsg != WM_MOUSEWHEEL) { + if (mb.pressed) { + + if (++pressrc>0) + SetCapture(hWnd); + } else { + + + if (--pressrc<=0) { + ReleaseCapture(); + pressrc=0; + } + + } + } else if (mouse_mode!=MOUSE_MODE_CAPTURED) { + // for reasons unknown to mankind, wheel comes in screen cordinates + RECT rect; + GetWindowRect(hWnd,&rect); + mb.x-=rect.left; + mb.y-=rect.top; + + } + + if (main_loop) { + input->parse_input_event(event); + if (mb.pressed && mb.button_index>3) { + //send release for mouse wheel + mb.pressed=false; + event.ID=++last_id; + input->parse_input_event(event); + + } + } + + + + } break; + + case WM_SIZE: { + video_mode.width=LOWORD(lParam); + video_mode.height=HIWORD(lParam); + //return 0; // Jump Back + } break; + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_KEYUP: + case WM_KEYDOWN: { + + + if (wParam==VK_SHIFT) + shift_mem=uMsg==WM_KEYDOWN; + if (wParam==VK_CONTROL) + control_mem=uMsg==WM_KEYDOWN; + if (wParam==VK_MENU) { + alt_mem=(uMsg==WM_KEYDOWN || uMsg==WM_SYSKEYDOWN); + if (lParam&(1<<24)) + gr_mem=alt_mem; + } + + //if (wParam==VK_WIN) TODO wtf is this? + // meta_mem=uMsg==WM_KEYDOWN; + + + } //fallthrough + case WM_CHAR: { + + ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); + + KeyEvent ke; + ke.mod_state.shift=shift_mem; + ke.mod_state.alt=alt_mem; + ke.mod_state.control=control_mem; + ke.mod_state.meta=meta_mem; + ke.uMsg=uMsg; + + if (ke.uMsg==WM_SYSKEYDOWN) + ke.uMsg=WM_KEYDOWN; + if (ke.uMsg==WM_SYSKEYUP) + ke.uMsg=WM_KEYUP; + + + /*if (ke.uMsg==WM_KEYDOWN && alt_mem && uMsg!=WM_SYSKEYDOWN) { + //altgr hack for intl keyboards, not sure how good it is + //windows is weeeeird + ke.mod_state.alt=false; + ke.mod_state.control=false; + print_line("") + }*/ + + + ke.wParam=wParam; + ke.lParam=lParam; + key_event_buffer[key_event_pos++]=ke; + + } break; + case WM_INPUTLANGCHANGEREQUEST: { + + print_line("input lang change"); + } break; + default: { + + if (user_proc) { + + return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam); + }; + }; + } + + return DefWindowProcW(hWnd,uMsg,wParam,lParam); + +} + +LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { + + OS_Windows *os_win = static_cast<OS_Windows*>(OS::get_singleton()); + if (os_win) + return os_win->WndProc(hWnd,uMsg,wParam,lParam); + else + return DefWindowProcW(hWnd,uMsg,wParam,lParam); + +} + +void OS_Windows::probe_joysticks() { + + int device_count = joyGetNumDevs(); + + JOYINFOEX jinfo; + jinfo.dwSize = sizeof(JOYINFOEX); + jinfo.dwFlags = JOY_RETURNALL; + + for (int i=0; i<JOYSTICKS_MAX; i++) { + + joysticks[i].attached = (device_count > 0) && (joyGetPosEx(JOYSTICKID1 + i, &jinfo) == JOYERR_NOERROR); + + if (!joysticks[i].attached) { + + continue; + }; + + joysticks[i].last_buttons = jinfo.dwButtons; + + joysticks[i].last_axis[0] = jinfo.dwXpos; + joysticks[i].last_axis[1] = jinfo.dwYpos; + joysticks[i].last_axis[2] = jinfo.dwZpos; + joysticks[i].last_axis[3] = jinfo.dwRpos; + joysticks[i].last_axis[4] = jinfo.dwUpos; + joysticks[i].last_axis[5] = jinfo.dwVpos; + }; +}; + +void OS_Windows::process_key_events() { + + for(int i=0;i<key_event_pos;i++) { + + KeyEvent &ke = key_event_buffer[i]; + switch(ke.uMsg) { + + case WM_CHAR: { + + //do nothing + } break; + case WM_KEYUP: + case WM_KEYDOWN: { + + + InputEvent event; + event.type=InputEvent::KEY; + event.ID=++last_id; + InputEventKey &k=event.key; + + + k.mod=ke.mod_state; + k.pressed=(ke.uMsg==WM_KEYDOWN); + + k.scancode=KeyMappingWindows::get_keysym(ke.wParam); + if (i+1 < key_event_pos && key_event_buffer[i+1].uMsg==WM_CHAR) + k.unicode=key_event_buffer[i+1].wParam; + if (k.unicode && gr_mem) { + k.mod.alt=false; + k.mod.control=false; + } + + if (k.unicode<32) + k.unicode=0; + + + + k.echo=(ke.uMsg==WM_KEYDOWN && (ke.lParam&(1<<30))); + + input->parse_input_event(event); + + + } break; + } + } + + key_event_pos=0; +} + +void OS_Windows::_post_dpad(DWORD p_dpad, int p_device, bool p_pressed) { + + InputEvent ievent; + ievent.device = p_device; + ievent.type = InputEvent::JOYSTICK_BUTTON; + ievent.joy_button.pressed = p_pressed; + ievent.joy_button.pressure = p_pressed ? 1.0 : 0.0; + + if (p_dpad == 0) { + + ievent.joy_button.button_index = JOY_DPAD_UP; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + } else if (p_dpad == 4500) { + + ievent.joy_button.button_index = JOY_DPAD_UP; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + ievent.joy_button.button_index = JOY_DPAD_RIGHT; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + } else if (p_dpad == 9000) { + + ievent.joy_button.button_index = JOY_DPAD_RIGHT; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + } else if (p_dpad == 13500) { + + ievent.joy_button.button_index = JOY_DPAD_RIGHT; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + ievent.joy_button.button_index = JOY_DPAD_DOWN; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + } else if (p_dpad == 18000) { + + ievent.joy_button.button_index = JOY_DPAD_DOWN; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + } else if (p_dpad == 22500) { + + ievent.joy_button.button_index = JOY_DPAD_DOWN; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + ievent.joy_button.button_index = JOY_DPAD_LEFT; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + } else if (p_dpad == 27000) { + + ievent.joy_button.button_index = JOY_DPAD_LEFT; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + } else if (p_dpad == 31500) { + + ievent.joy_button.button_index = JOY_DPAD_LEFT; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + + ievent.joy_button.button_index = JOY_DPAD_UP; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + }; +}; + +void OS_Windows::process_joysticks() { + + if (!main_loop) { + return; + }; + + InputEvent ievent; + + JOYINFOEX jinfo; + jinfo.dwSize = sizeof(JOYINFOEX); + jinfo.dwFlags = JOY_RETURNALL; + + for (int i=0; i<JOYSTICKS_MAX; i++) { + + if (!joysticks[i].attached) { + continue; + }; + + if (joyGetPosEx(JOYSTICKID1 + i, &jinfo) != JOYERR_NOERROR) { + + continue; + }; + + ievent.device = i; + + #define CHECK_AXIS(n, var) \ + if (joysticks[i].last_axis[n] != var) {\ + ievent.type = InputEvent::JOYSTICK_MOTION;\ + ievent.ID = ++last_id;\ + ievent.joy_motion.axis = n;\ + ievent.joy_motion.axis_value = (float)((int)var - MAX_JOY_AXIS) / (float)MAX_JOY_AXIS;\ + joysticks[i].last_axis[n] = var;\ + input->parse_input_event(ievent);\ + }; + + CHECK_AXIS(0, jinfo.dwXpos); + CHECK_AXIS(1, jinfo.dwYpos); + CHECK_AXIS(2, jinfo.dwZpos); + CHECK_AXIS(3, jinfo.dwRpos); + CHECK_AXIS(4, jinfo.dwUpos); + CHECK_AXIS(5, jinfo.dwVpos); + + if (joysticks[i].last_pov != jinfo.dwPOV) { + + if (joysticks[i].last_pov != JOY_POVCENTERED) + _post_dpad(joysticks[i].last_pov, i, false); + + if (jinfo.dwPOV != JOY_POVCENTERED) + _post_dpad(jinfo.dwPOV, i, true); + + joysticks[i].last_pov = jinfo.dwPOV; + }; + + if (joysticks[i].last_buttons == jinfo.dwButtons) { + continue; + }; + + ievent.type = InputEvent::JOYSTICK_BUTTON; + for (int j=0; j<32; j++) { + + if ( (joysticks[i].last_buttons & (1<<j)) != (jinfo.dwButtons & (1<<j)) ) { + + ievent.joy_button.button_index = _pc_joystick_get_native_button(j); + ievent.joy_button.pressed = jinfo.dwButtons & 1<<j; + ievent.ID = ++last_id; + input->parse_input_event(ievent); + }; + }; + + joysticks[i].last_buttons = jinfo.dwButtons; + }; +}; + +void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { + + + + main_loop=NULL; + outside=true; + + WNDCLASSEXW wc; + + video_mode=p_desired; + //printf("**************** desired %s, mode %s\n", p_desired.fullscreen?"true":"false", video_mode.fullscreen?"true":"false"); + RECT WindowRect; + + WindowRect.left=0; + WindowRect.right=video_mode.width; + WindowRect.top=0; + WindowRect.bottom=video_mode.height; + + memset(&wc,0,sizeof(WNDCLASSEXW)); + wc.cbSize=sizeof(WNDCLASSEXW); + wc.style= CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; + wc.lpfnWndProc = (WNDPROC)::WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra= 0; + //wc.hInstance = hInstance; + wc.hInstance = godot_hinstance ? godot_hinstance : GetModuleHandle(NULL); + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = L"Engine"; + + if (!RegisterClassExW(&wc)) { + MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return; // Return + } + + + if (video_mode.fullscreen) { + + DEVMODE current; + memset(¤t,0,sizeof(current)); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤t); + + DEVMODE dmScreenSettings; + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); + dmScreenSettings.dmSize=sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = video_mode.width; + dmScreenSettings.dmPelsHeight = video_mode.height; + dmScreenSettings.dmBitsPerPel = current.dmBitsPerPel; + dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + LONG err = ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN); + if (err!=DISP_CHANGE_SUCCESSFUL) { + + video_mode.fullscreen=false; + } + } + + DWORD dwExStyle; + DWORD dwStyle; + + if (video_mode.fullscreen) { + + dwExStyle=WS_EX_APPWINDOW; + dwStyle=WS_POPUP; + + } else { + dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle=WS_OVERLAPPEDWINDOW; + } + + AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); + + + char* windowid = getenv("GODOT_WINDOWID"); + if (windowid) { + + // strtoull on mingw + #ifdef MINGW_ENABLED + hWnd = (HWND)strtoull(windowid, NULL, 0); + #else + hWnd = (HWND)_strtoui64(windowid, NULL, 0); + #endif + SetLastError(0); + user_proc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC); + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)::WndProc); + DWORD le = GetLastError(); + if (user_proc == 0 && le != 0) { + + printf("Error setting WNDPROC: %li\n", le); + }; + LONG_PTR proc = GetWindowLongPtr(hWnd, GWLP_WNDPROC); + + RECT rect; + if (!GetClientRect(hWnd, &rect)) { + MessageBoxW(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION); + return; // Return FALSE + }; + video_mode.width = rect.right; + video_mode.height = rect.bottom; + video_mode.fullscreen = false; + } else { + + if (!(hWnd=CreateWindowExW(dwExStyle,L"Engine",L"", dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, 0, 0,WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top, NULL,NULL, hInstance,NULL))) { + MessageBoxW(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION); + return; // Return FALSE + } + + + }; + +#if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) || defined(LEGACYGL_ENABLED) + gl_context = memnew( ContextGL_Win(hWnd,false) ); + gl_context->initialize(); + rasterizer = memnew( RasterizerGLES2 ); +#else + #ifdef DX9_ENABLED + rasterizer = memnew( RasterizerDX9(hWnd) ); + #endif +#endif + + visual_server = memnew( VisualServerRaster(rasterizer) ); + if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) { + + visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD)); + } + + // + physics_server = memnew( PhysicsServerSW ); + physics_server->init(); + + physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server->init(); + + if (!is_no_window_mode_enabled()) { + ShowWindow(hWnd,SW_SHOW); // Show The Window + SetForegroundWindow(hWnd); // Slightly Higher Priority + SetFocus(hWnd); // Sets Keyboard Focus To + } + +/* + DEVMODE dmScreenSettings; // Device Mode + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared + dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure + dmScreenSettings.dmPelsWidth = width; // Selected Screen Width + dmScreenSettings.dmPelsHeight = height; // Selected Screen Height + dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel + dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) + + + + + */ + visual_server->init(); + + input = memnew( InputDefault ); + + AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); + + if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) { + + ERR_PRINT("Initializing audio failed."); + } + + sample_manager = memnew( SampleManagerMallocSW ); + audio_server = memnew( AudioServerSW(sample_manager) ); + + audio_server->init(); + + spatial_sound_server = memnew( SpatialSoundServerSW ); + spatial_sound_server->init(); + spatial_sound_2d_server = memnew( SpatialSound2DServerSW ); + spatial_sound_2d_server->init(); + + probe_joysticks(); + + TRACKMOUSEEVENT tme; + tme.cbSize=sizeof(TRACKMOUSEEVENT); + tme.dwFlags=TME_LEAVE; + tme.hwndTrack=hWnd; + tme.dwHoverTime=HOVER_DEFAULT; + TrackMouseEvent(&tme); + + + _ensure_data_dir(); + + +} + +void OS_Windows::set_clipboard(const String& p_text) { + + if (!OpenClipboard(hWnd)) { + ERR_EXPLAIN("Unable to open clipboard."); + ERR_FAIL(); + }; + EmptyClipboard(); + + HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (p_text.length() + 1) * sizeof(CharType)); + if (mem == NULL) { + ERR_EXPLAIN("Unable to allocate memory for clipboard contents."); + ERR_FAIL(); + }; + LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem); + memcpy(lptstrCopy, p_text.c_str(), (p_text.length() + 1) * sizeof(CharType)); + //memset((lptstrCopy + p_text.length()), 0, sizeof(CharType)); + GlobalUnlock(mem); + + SetClipboardData(CF_UNICODETEXT, mem); + + // set the CF_TEXT version (not needed?) + CharString utf8 = p_text.utf8(); + mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1); + if (mem == NULL) { + ERR_EXPLAIN("Unable to allocate memory for clipboard contents."); + ERR_FAIL(); + }; + LPTSTR ptr = (LPTSTR)GlobalLock(mem); + memcpy(ptr, utf8.get_data(), utf8.length()); + ptr[utf8.length()] = 0; + GlobalUnlock(mem); + + SetClipboardData(CF_TEXT, mem); + + CloseClipboard(); +}; + +String OS_Windows::get_clipboard() const { + + String ret; + if (!OpenClipboard(hWnd)) { + ERR_EXPLAIN("Unable to open clipboard."); + ERR_FAIL_V(""); + }; + + if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { + + HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); + if (mem != NULL) { + + LPWSTR ptr = (LPWSTR)GlobalLock(mem); + if (ptr != NULL) { + + ret = String((CharType*)ptr); + GlobalUnlock(mem); + }; + }; + + } else if (IsClipboardFormatAvailable(CF_TEXT)) { + + HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); + if (mem != NULL) { + + LPTSTR ptr = (LPTSTR)GlobalLock(mem); + if (ptr != NULL) { + + ret.parse_utf8((const char*)ptr); + GlobalUnlock(mem); + }; + }; + }; + + CloseClipboard(); + + return ret; +}; + + +void OS_Windows::delete_main_loop() { + + if (main_loop) + memdelete(main_loop); + main_loop=NULL; +} + +void OS_Windows::set_main_loop( MainLoop * p_main_loop ) { + + input->set_main_loop(p_main_loop); + main_loop=p_main_loop; +} + +void OS_Windows::finalize() { + + if(main_loop) + memdelete(main_loop); + + main_loop=NULL; + + visual_server->finish(); + memdelete(visual_server); +#ifdef OPENGL_ENABLED + if (gl_context) + memdelete(gl_context); +#endif + if (rasterizer) + memdelete(rasterizer); + + if (user_proc) { + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc); + }; + + spatial_sound_server->finish(); + memdelete(spatial_sound_server); + spatial_sound_2d_server->finish(); + memdelete(spatial_sound_2d_server); + + //if (debugger_connection_console) { +// memdelete(debugger_connection_console); +//} + + audio_server->finish(); + memdelete(audio_server); + memdelete(sample_manager); + + memdelete(input); + + physics_server->finish(); + memdelete(physics_server); + + physics_2d_server->finish(); + memdelete(physics_2d_server); + +} +void OS_Windows::finalize_core() { + + memdelete(process_map); + + if (mempool_dynamic) + memdelete( mempool_dynamic ); + if (mempool_static) + delete mempool_static; + + + TCPServerWinsock::cleanup(); + StreamPeerWinsock::cleanup(); +} + +void OS_Windows::vprint(const char* p_format, va_list p_list, bool p_stderr) { + + char buf[16384+1]; + int len = vsnprintf(buf,16384,p_format,p_list); + if (len<=0) + return; + buf[len]=0; + + + int wlen = MultiByteToWideChar(CP_UTF8,0,buf,len,NULL,0); + if (wlen<0) + return; + + wchar_t *wbuf = (wchar_t*)malloc((len+1)*sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8,0,buf,len,wbuf,wlen); + wbuf[wlen]=0; + + if (p_stderr) + fwprintf(stderr,L"%s",wbuf); + else + wprintf(L"%s",wbuf); + +#ifdef STDOUT_FILE + //vwfprintf(stdo,p_format,p_list); +#endif + free(wbuf); + + fflush(stdout); +}; + +void OS_Windows::alert(const String& p_alert,const String& p_title) { + + if (!is_no_window_mode_enabled()) + MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION); + else + print_line("ALERT: "+p_alert); +} + +void OS_Windows::set_mouse_mode(MouseMode p_mode) { + + if (mouse_mode==p_mode) + return; + ShowCursor(p_mode==MOUSE_MODE_VISIBLE); + mouse_mode=p_mode; + if (p_mode==MOUSE_MODE_CAPTURED) { + RECT clipRect; + GetClientRect(hWnd, &clipRect); + ClientToScreen(hWnd, (POINT*) &clipRect.left); + ClientToScreen(hWnd, (POINT*) &clipRect.right); + ClipCursor(&clipRect); + SetCapture(hWnd); + center=Point2i(video_mode.width/2,video_mode.height/2); + POINT pos = { (int) center.x, (int) center.y }; + ClientToScreen(hWnd, &pos); + SetCursorPos(pos.x, pos.y); + } else { + ReleaseCapture(); + ClipCursor(NULL); + } + +} + +OS_Windows::MouseMode OS_Windows::get_mouse_mode() const{ + + return mouse_mode; +} + + + +Point2 OS_Windows::get_mouse_pos() const { + + return Point2(old_x, old_y); +} + +int OS_Windows::get_mouse_button_state() const { + + return last_button_state; +} + +void OS_Windows::set_window_title(const String& p_title) { + + SetWindowTextW(hWnd,p_title.c_str()); +} + +void OS_Windows::set_video_mode(const VideoMode& p_video_mode,int p_screen) { + + +} +OS::VideoMode OS_Windows::get_video_mode(int p_screen) const { + + return video_mode; +} +void OS_Windows::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const { + + +} + +void OS_Windows::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) { + + HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE); + if (!hCon || hCon==INVALID_HANDLE_VALUE) { + if (p_rationale && p_rationale[0]) { + + print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale); + print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line); + + } else { + print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code); + print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line); + + } + } else { + + CONSOLE_SCREEN_BUFFER_INFO sbi; //original + GetConsoleScreenBufferInfo(hCon,&sbi); + + SetConsoleTextAttribute(hCon,sbi.wAttributes); + + + + uint32_t basecol=0; + switch(p_type) { + case ERR_ERROR: basecol = FOREGROUND_RED; break; + case ERR_WARNING: basecol = FOREGROUND_RED|FOREGROUND_GREEN; break; + case ERR_SCRIPT: basecol = FOREGROUND_GREEN; break; + } + + if (p_rationale && p_rationale[0]) { + + SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY); + + + switch(p_type) { + case ERR_ERROR: print("ERROR: "); break; + case ERR_WARNING: print("WARNING: "); break; + case ERR_SCRIPT: print("SCRIPT ERROR: "); break; + } + + SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY); + print(" %s\n",p_rationale); + SetConsoleTextAttribute(hCon,basecol); + print("At: "); + SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN); + print(" %s:%i\n",p_file,p_line); + + + } else { + SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY); + switch(p_type) { + case ERR_ERROR: print("ERROR: %s: ",p_function); break; + case ERR_WARNING: print("WARNING: %s: ",p_function); break; + case ERR_SCRIPT: print("SCRIPT ERROR: %s: ",p_function); break; + } + SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY); + print(" %s\n",p_code); + SetConsoleTextAttribute(hCon,basecol); + print("At: "); + SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN); + print(" %s:%i\n",p_file,p_line); + } + + SetConsoleTextAttribute(hCon,sbi.wAttributes); + } + +} + + +String OS_Windows::get_name() { + + return "Windows"; +} + +OS::Date OS_Windows::get_date() const { + + SYSTEMTIME systemtime; + GetSystemTime(&systemtime); + Date date; + date.day=systemtime.wDay; + date.month=Month(systemtime.wMonth); + date.weekday=Weekday(systemtime.wDayOfWeek); + date.year=systemtime.wYear; + date.dst=false; + return date; +} +OS::Time OS_Windows::get_time() const { + + SYSTEMTIME systemtime; + GetSystemTime(&systemtime); + + Time time; + time.hour=systemtime.wHour; + time.min=systemtime.wMinute; + time.sec=systemtime.wSecond; + return time; +} + +uint64_t OS_Windows::get_unix_time() const { + + FILETIME ft; + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + + SYSTEMTIME ep; + ep.wYear = 1970; + ep.wMonth = 1; + ep.wDayOfWeek = 4; + ep.wDay = 1; + ep.wHour = 0; + ep.wMinute = 0; + ep.wSecond = 0; + ep.wMilliseconds = 0; + FILETIME fep; + SystemTimeToFileTime(&ep, &fep); + + return (*(uint64_t*)&ft - *(uint64_t*)&fep) / 10000000; +}; + +void OS_Windows::delay_usec(uint32_t p_usec) const { + + if (p_usec < 1000) + Sleep(1); + else + Sleep(p_usec / 1000); + +} +uint64_t OS_Windows::get_ticks_usec() const { + + uint64_t ticks; + uint64_t time; + // This is the number of clock ticks since start + if( !QueryPerformanceCounter((LARGE_INTEGER *)&ticks) ) + ticks = (UINT64)timeGetTime(); + // Divide by frequency to get the time in seconds + time = ticks * 1000000L / ticks_per_second; + // Subtract the time at game start to get + // the time since the game started + time -= ticks_start; + return time; +} + + +void OS_Windows::process_events() { + + MSG msg; + + process_joysticks(); + + while(PeekMessageW(&msg,NULL,0,0,PM_REMOVE)) { + + + TranslateMessage(&msg); + DispatchMessageW(&msg); + + } + + process_key_events(); + +} + +void OS_Windows::set_cursor_shape(CursorShape p_shape) { + + ERR_FAIL_INDEX(p_shape,CURSOR_MAX); + + if (cursor_shape==p_shape) + return; + + static const LPCTSTR win_cursors[CURSOR_MAX]={ + IDC_ARROW, + IDC_IBEAM, + IDC_HAND,//finger + IDC_CROSS, + IDC_WAIT, + IDC_APPSTARTING, + IDC_ARROW, + IDC_ARROW, + IDC_NO, + IDC_SIZENS, + IDC_SIZEWE, + IDC_SIZENESW, + IDC_SIZENWSE, + IDC_SIZEALL, + IDC_SIZENS, + IDC_SIZEWE, + IDC_HELP + }; + + SetCursor(LoadCursor(hInstance,win_cursors[p_shape])); + cursor_shape=p_shape; +} + +Error OS_Windows::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) { + + if (p_blocking && r_pipe) { + + + String argss; + argss="\"\""+p_path+"\""; + + for(int i=0;i<p_arguments.size();i++) { + + argss+=String(" \"")+p_arguments[i]+"\""; + } + +// print_line("ARGS: "+argss); + //argss+"\""; + //argss+=" 2>nul"; + + FILE* f=_wpopen(argss.c_str(),L"r"); + + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + char buf[65535]; + while(fgets(buf,65535,f)) { + + (*r_pipe)+=buf; + } + + int rv = _pclose(f); + if (r_exitcode) + *r_exitcode=rv; + + return OK; + } + + String cmdline = "\""+p_path+"\""; + const List<String>::Element* I = p_arguments.front(); + while (I) { + + + cmdline += " \""+I->get() + "\""; + + I = I->next(); + }; + + //cmdline+="\""; + + ProcessInfo pi; + ZeroMemory( &pi.si, sizeof(pi.si) ); + pi.si.cb = sizeof(pi.si); + ZeroMemory( &pi.pi, sizeof(pi.pi) ); + + print_line("running cmdline: "+cmdline); + + int ret = CreateProcess(NULL, (LPSTR)cmdline.utf8().get_data(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS, NULL, NULL, &pi.si, &pi.pi); + ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK); + + if (p_blocking) { + + DWORD ret = WaitForSingleObject(pi.pi.hProcess, INFINITE); + if (r_exitcode) + *r_exitcode=ret; + + } else { + + ProcessID pid = pi.pi.dwProcessId; + if (r_child_id) { + *r_child_id = pid; + }; + process_map->insert(pid, pi); + }; + return OK; +}; + +Error OS_Windows::kill(const ProcessID& p_pid) { + + HANDLE h; + + if (process_map->has(p_pid)) { + h = (*process_map)[p_pid].pi.hProcess; + process_map->erase(p_pid); + } else { + + ERR_FAIL_COND_V(!process_map->has(p_pid), FAILED); + }; + + int ret = TerminateProcess(h, 0); + + return ret != 0?OK:FAILED; +}; + +Error OS_Windows::set_cwd(const String& p_cwd) { + + if (_wchdir(p_cwd.c_str())!=0) + return ERR_CANT_OPEN; + + return OK; +} + +void OS_Windows::set_icon(const Image& p_icon) { + + + Image icon=p_icon; + if (icon.get_format()!=Image::FORMAT_RGBA) + icon.convert(Image::FORMAT_RGBA); + int w = icon.get_width(); + int h = icon.get_height(); + + /* Create temporary bitmap buffer */ + int icon_len = 40 + h * w * 4; + BYTE *icon_bmp = (BYTE*)alloca(icon_len); + + encode_uint32(40,&icon_bmp[0]); + encode_uint32(w,&icon_bmp[4]); + encode_uint32(h*2,&icon_bmp[8]); + encode_uint16(1,&icon_bmp[12]); + encode_uint16(32,&icon_bmp[14]); + encode_uint32(BI_RGB,&icon_bmp[16]); + encode_uint32(w*h*4,&icon_bmp[20]); + encode_uint32(0,&icon_bmp[24]); + encode_uint32(0,&icon_bmp[28]); + encode_uint32(0,&icon_bmp[32]); + encode_uint32(0,&icon_bmp[36]); + + uint8_t *wr=&icon_bmp[40]; + DVector<uint8_t>::Read r= icon.get_data().read(); + + for(int i=0;i<h;i++) { + + for(int j=0;j<w;j++) { + + const uint8_t *rpx = &r[((h-i-1)*w+j)*4]; + uint8_t *wpx = &wr[(i*w+j)*4]; + wpx[0]=rpx[2]; + wpx[1]=rpx[1]; + wpx[2]=rpx[0]; + wpx[3]=rpx[3]; + } + } + + + HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000); + + /* Set the icon for the window */ + SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon); + + /* Set the icon in the task manager (should we do this?) */ + SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hicon); +} + + +bool OS_Windows::has_environment(const String& p_var) const { + + return getenv(p_var.utf8().get_data()) != NULL; +}; + +String OS_Windows::get_environment(const String& p_var) const { + + return getenv(p_var.utf8().get_data()); +}; + +String OS_Windows::get_stdin_string(bool p_block) { + + if (p_block) { + char buff[1024]; + return fgets(buff,1024,stdin); + }; + + return String(); +} + + +void OS_Windows::move_window_to_foreground() { + + SetForegroundWindow(hWnd); + +} + +String OS_Windows::get_locale() const { + + const _WinLocale *wl = &_win_locales[0]; + + LANGID langid = GetUserDefaultUILanguage(); + String neutral; + int lang = langid&((1<<9)-1); + int sublang = langid&~((1<<9)-1); + + while(wl->locale) { + + if (wl->main_lang==lang && wl->sublang==SUBLANG_NEUTRAL) + neutral=wl->locale; + + if (lang==wl->main_lang && sublang==wl->sublang) + return wl->locale; + + + wl++; + } + + if (neutral!="") + return neutral; + + return "en"; +} + +void OS_Windows::release_rendering_thread() { + + gl_context->release_current(); + +} + +void OS_Windows::make_rendering_thread() { + + gl_context->make_current(); +} + +void OS_Windows::swap_buffers() { + + gl_context->swap_buffers(); +} + + +void OS_Windows::run() { + + if (!main_loop) + return; + + main_loop->init(); + + uint64_t last_ticks=get_ticks_usec(); + + int frames=0; + uint64_t frame=0; + + while (!force_quit) { + + process_events(); // get rid of pending events + if (Main::iteration()==true) + break; + }; + + main_loop->finish(); + +} + + + +MainLoop *OS_Windows::get_main_loop() const { + + return main_loop; +} + + +String OS_Windows::get_data_dir() const { + + String an = Globals::get_singleton()->get("application/name"); + if (an!="") { + + if (has_environment("APPDATA")) { + + return OS::get_singleton()->get_environment("APPDATA")+"\\"+an; + } + } + + return Globals::get_singleton()->get_resource_path(); + + +} + + +OS_Windows::OS_Windows(HINSTANCE _hInstance) { + + key_event_pos=0; + force_quit=false; + alt_mem=false; + gr_mem=false; + shift_mem=false; + control_mem=false; + meta_mem=false; + minimized = false; + + hInstance=_hInstance; + pressrc=0; + old_invalid=true; + last_id=0; + mouse_mode=MOUSE_MODE_VISIBLE; +#ifdef STDOUT_FILE + stdo=fopen("stdout.txt","wb"); +#endif + user_proc = NULL; + +#ifdef RTAUDIO_ENABLED + AudioDriverManagerSW::add_driver(&driver_rtaudio); +#endif + +} + + +OS_Windows::~OS_Windows() +{ +#ifdef STDOUT_FILE + fclose(stdo); +#endif +} + + diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h new file mode 100644 index 0000000000..5587d89763 --- /dev/null +++ b/platform/windows/os_windows.h @@ -0,0 +1,257 @@ +/*************************************************************************/ +/* os_windows.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef OS_WINDOWS_H +#define OS_WINDOWS_H + +#define WINVER 0x0500 + +#include "os/input.h" +#include "os/os.h" +#include "context_gl_win.h" +#include "servers/visual_server.h" +#include "servers/visual/rasterizer.h" +#include "servers/physics/physics_server_sw.h" + +#include "servers/audio/audio_server_sw.h" +#include "servers/audio/sample_manager_sw.h" +#include "drivers/rtaudio/audio_driver_rtaudio.h" +#include "servers/spatial_sound/spatial_sound_server_sw.h" +#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" +#include "drivers/unix/ip_unix.h" +#include "servers/physics_2d/physics_2d_server_sw.h" + + +#include <windows.h> + +#include "key_mapping_win.h" +#include <windowsx.h> +#include <io.h> + +#include <fcntl.h> +#include <stdio.h> +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class OS_Windows : public OS { + + enum { + JOYSTICKS_MAX = 8, + JOY_AXIS_COUNT = 6, + MAX_JOY_AXIS = 32768, // I've no idea + KEY_EVENT_BUFFER_SIZE=512 + }; + + FILE *stdo; + + + struct KeyEvent { + + InputModifierState mod_state; + UINT uMsg; + WPARAM wParam; + LPARAM lParam; + + }; + + KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE]; + int key_event_pos; + + + uint64_t ticks_start; + uint64_t ticks_per_second; + + bool minimized; + bool old_invalid; + bool outside; + int old_x,old_y; + Point2i center; + unsigned int last_id; +#if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) || defined(GLES2_ENABLED) + ContextGL_Win *gl_context; +#endif + VisualServer *visual_server; + Rasterizer *rasterizer; + PhysicsServer *physics_server; + Physics2DServer *physics_2d_server; + int pressrc; + HDC hDC; // Private GDI Device Context + HINSTANCE hInstance; // Holds The Instance Of The Application + HWND hWnd; + + struct Joystick { + + bool attached; + + DWORD last_axis[JOY_AXIS_COUNT]; + DWORD last_buttons; + DWORD last_pov; + + Joystick() { + attached = false; + for (int i=0; i<JOY_AXIS_COUNT; i++) { + + last_axis[i] = 0; + }; + last_buttons = 0; + last_pov = 0; + }; + }; + + int joystick_count; + Joystick joysticks[JOYSTICKS_MAX]; + + VideoMode video_mode; + + MainLoop *main_loop; + + WNDPROC user_proc; + + AudioServerSW *audio_server; + SampleManagerMallocSW *sample_manager; + SpatialSoundServerSW *spatial_sound_server; + SpatialSound2DServerSW *spatial_sound_2d_server; + + MouseMode mouse_mode; + bool alt_mem; + bool gr_mem; + bool shift_mem; + bool control_mem; + bool meta_mem; + bool force_quit; + uint32_t last_button_state; + + CursorShape cursor_shape; + + InputDefault *input; + +#ifdef RTAUDIO_ENABLED + AudioDriverRtAudio driver_rtaudio; +#endif + + void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed); + + // functions used by main to initialize/deintialize the OS +protected: + virtual int get_video_driver_count() const; + virtual const char * get_video_driver_name(int p_driver) const; + + virtual VideoMode get_default_video_mode() const; + + virtual int get_audio_driver_count() const; + virtual const char * get_audio_driver_name(int p_driver) const; + + virtual void initialize_core(); + virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver); + + virtual void set_main_loop( MainLoop * p_main_loop ); + virtual void delete_main_loop(); + + virtual void finalize(); + virtual void finalize_core(); + + void process_events(); + + void probe_joysticks(); + void process_joysticks(); + void process_key_events(); + + struct ProcessInfo { + + STARTUPINFO si; + PROCESS_INFORMATION pi; + }; + Map<ProcessID, ProcessInfo>* process_map; + +public: + LRESULT WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam); + + + void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type); + + virtual void vprint(const char *p_format, va_list p_list, bool p_stderr=false); + virtual void alert(const String& p_alert,const String& p_title="ALERT!"); + String get_stdin_string(bool p_block); + + void set_mouse_mode(MouseMode p_mode); + MouseMode get_mouse_mode() const; + + virtual Point2 get_mouse_pos() const; + virtual int get_mouse_button_state() const; + virtual void set_window_title(const String& p_title); + + virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0); + virtual VideoMode get_video_mode(int p_screen=0) const; + virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const; + + virtual MainLoop *get_main_loop() const; + + virtual String get_name(); + + virtual Date get_date() const; + virtual Time get_time() const; + virtual uint64_t get_unix_time() const; + + virtual bool can_draw() const; + virtual Error set_cwd(const String& p_cwd); + + virtual void delay_usec(uint32_t p_usec) const; + virtual uint64_t get_ticks_usec() const; + + virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL); + virtual Error kill(const ProcessID& p_pid); + + virtual bool has_environment(const String& p_var) const; + virtual String get_environment(const String& p_var) const; + + virtual void set_clipboard(const String& p_text); + virtual String get_clipboard() const; + + void set_cursor_shape(CursorShape p_shape); + void set_icon(const Image& p_icon); + + + virtual String get_locale() const; + + virtual void move_window_to_foreground(); + virtual String get_data_dir() const; + + virtual void release_rendering_thread(); + virtual void make_rendering_thread(); + virtual void swap_buffers(); + + void run(); + + virtual bool get_swap_ok_cancel() { return true; } + + OS_Windows(HINSTANCE _hInstance); + ~OS_Windows(); + +}; + +#endif diff --git a/platform/windows/platform_config.h b/platform/windows/platform_config.h new file mode 100644 index 0000000000..7bc3e42833 --- /dev/null +++ b/platform/windows/platform_config.h @@ -0,0 +1,35 @@ +/*************************************************************************/ +/* platform_config.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include <malloc.h> +//#else +//#include <alloca.h> +//#endif +#define GLES2_INCLUDE_H "gl_context/glew.h" +#define GLES1_INCLUDE_H "gl_context/glew.h" + diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp new file mode 100644 index 0000000000..2c3a8db7b1 --- /dev/null +++ b/platform/windows/stream_peer_winsock.cpp @@ -0,0 +1,368 @@ +/*************************************************************************/ +/* stream_peer_winsock.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef WINDOWS_ENABLED + +#include "stream_peer_winsock.h" + +#include <winsock2.h> + +int winsock_refcount = 0; + +static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { + + their_addr.sin_family = AF_INET; // host byte order + their_addr.sin_port = htons(p_port); // short, network byte order + their_addr.sin_addr = *((struct in_addr*)&p_host.host); + memset(&(their_addr.sin_zero), '\0', 8); +}; + +StreamPeerTCP* StreamPeerWinsock::_create() { + + return memnew(StreamPeerWinsock); +}; + +void StreamPeerWinsock::make_default() { + + StreamPeerTCP::_create = StreamPeerWinsock::_create; + + if (winsock_refcount == 0) { + WSADATA data; + WSAStartup(MAKEWORD(2,2), &data); + }; + ++winsock_refcount; +}; + +void StreamPeerWinsock::cleanup() { + + --winsock_refcount; + if (winsock_refcount == 0) { + + WSACleanup(); + }; +}; + + +Error StreamPeerWinsock::_block(int p_sockfd, bool p_read, bool p_write) const { + + fd_set read, write; + FD_ZERO(&read); + FD_ZERO(&write); + + if (p_read) + FD_SET(p_sockfd, &read); + if (p_write) + FD_SET(p_sockfd, &write); + + int ret = select(p_sockfd + 1, &read, &write, NULL, NULL); // block forever + return ret < 0 ? FAILED : OK; +}; + +Error StreamPeerWinsock::_poll_connection(bool p_block) const { + + ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == INVALID_SOCKET, FAILED); + + if (p_block) { + + _block(sockfd, false, true); + }; + + struct sockaddr_in their_addr; + set_addr_in(their_addr, peer_host, peer_port); + + if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + + int err = WSAGetLastError(); + if (err == WSAEISCONN) { + status = STATUS_CONNECTED; + return OK; + }; + + return OK; + } else { + + status = STATUS_CONNECTED; + return OK; + }; + + return OK; +}; + +Error StreamPeerWinsock::write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block) { + + if (status == STATUS_NONE || status == STATUS_ERROR) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + + if (_poll_connection(p_block) != OK) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + r_sent = 0; + return OK; + }; + }; + + int data_to_send = p_bytes; + const uint8_t *offset = p_data; + if (sockfd == -1) return FAILED; + errno = 0; + int total_sent = 0; + + while (data_to_send) { + + int sent_amount = send(sockfd, (const char*)offset, data_to_send, 0); + //printf("Sent TCP data of %d bytes, errno %d\n", sent_amount, errno); + + if (sent_amount == -1) { + + if (WSAGetLastError() != WSAEWOULDBLOCK) { + + perror("shit?"); + disconnect(); + ERR_PRINT("Server disconnected!\n"); + return FAILED; + }; + + if (!p_block) { + r_sent = total_sent; + return OK; + }; + + _block(sockfd, false, true); + } else { + + data_to_send -= sent_amount; + offset += sent_amount; + total_sent += sent_amount; + }; + } + + r_sent = total_sent; + + return OK; +}; + +Error StreamPeerWinsock::read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block) { + + if (!is_connected()) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + + if (_poll_connection(p_block) != OK) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + r_received = 0; + return OK; + }; + }; + + int to_read = p_bytes; + int total_read = 0; + errno = 0; + + while (to_read) { + + int read = recv(sockfd, (char*)p_buffer + total_read, to_read, 0); + + if (read == -1) { + + if (WSAGetLastError() != WSAEWOULDBLOCK) { + + perror("shit?"); + disconnect(); + ERR_PRINT("Server disconnected!\n"); + return FAILED; + }; + + if (!p_block) { + + r_received = total_read; + return OK; + }; + _block(sockfd, true, false); + } else if (read == 0) { + disconnect(); + return ERR_FILE_EOF; + } else { + + to_read -= read; + total_read += read; + }; + }; + + r_received = total_read; + + return OK; +}; + +Error StreamPeerWinsock::put_data(const uint8_t* p_data,int p_bytes) { + + int total; + return write(p_data, p_bytes, total, true); +}; + +Error StreamPeerWinsock::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent) { + + return write(p_data, p_bytes, r_sent, false); +}; + +Error StreamPeerWinsock::get_data(uint8_t* p_buffer, int p_bytes) { + + int total; + return read(p_buffer, p_bytes, total, true); +}; + +Error StreamPeerWinsock::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received) { + + return read(p_buffer, p_bytes, r_received, false); +}; + +StreamPeerTCP::Status StreamPeerWinsock::get_status() const { + + if (status == STATUS_CONNECTING) { + _poll_connection(false); + }; + + return status; +}; + + +bool StreamPeerWinsock::is_connected() const { + + if (status == STATUS_NONE || status == STATUS_ERROR) { + + return false; + }; + if (status != STATUS_CONNECTED) { + return true; + }; + + return (sockfd!=INVALID_SOCKET); +}; + +void StreamPeerWinsock::disconnect() { + + if (sockfd != INVALID_SOCKET) + closesocket(sockfd); + sockfd=INVALID_SOCKET; + + status = STATUS_NONE; + + peer_host = IP_Address(); + peer_port = 0; +}; + +void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port) { + + sockfd = p_sockfd; + status = STATUS_CONNECTING; + peer_host = p_host; + peer_port = p_port; +}; + +Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) { + + ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER); + + if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + ERR_PRINT("Socket creation failed!"); + disconnect(); + //perror("socket"); + return FAILED; + }; + + unsigned long par = 1; + if (ioctlsocket(sockfd, FIONBIO, &par)) { + perror("setting non-block mode"); + disconnect(); + return FAILED; + }; + + struct sockaddr_in their_addr; + set_addr_in(their_addr, p_host, p_port); + + if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR) { + + if (WSAGetLastError() != WSAEWOULDBLOCK) { + ERR_PRINT("Connection to remote host failed!"); + disconnect(); + return FAILED; + }; + status = STATUS_CONNECTING; + } else { + status = STATUS_CONNECTED; + }; + + peer_host = p_host; + peer_port = p_port; + + return OK; +}; + +void StreamPeerWinsock::set_nodelay(bool p_enabled) { + + +} + + +IP_Address StreamPeerWinsock::get_connected_host() const { + + return peer_host; +}; + +uint16_t StreamPeerWinsock::get_connected_port() const { + + return peer_port; +}; + +StreamPeerWinsock::StreamPeerWinsock() { + + sockfd = INVALID_SOCKET; + status = STATUS_NONE; + peer_port = 0; +}; + +StreamPeerWinsock::~StreamPeerWinsock() { + + disconnect(); +}; + + +#endif diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h new file mode 100644 index 0000000000..14dd5f0bb1 --- /dev/null +++ b/platform/windows/stream_peer_winsock.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* stream_peer_winsock.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef WINDOWS_ENABLED + +#ifndef STREAM_PEER_WINSOCK_H +#define STREAM_PEER_WINSOCK_H + +#include "error_list.h" + +#include "core/io/ip_address.h" +#include "core/io/stream_peer_tcp.h" + +class StreamPeerWinsock : public StreamPeerTCP { + +protected: + + mutable Status status; + + int sockfd; + + Error _block(int p_sockfd, bool p_read, bool p_write) const; + + Error _poll_connection(bool p_block) const; + + IP_Address peer_host; + int peer_port; + + Error write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block); + Error read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block); + + static StreamPeerTCP* _create(); + +public: + + virtual Error connect(const IP_Address& p_host, uint16_t p_port); + + virtual Error put_data(const uint8_t* p_data,int p_bytes); + virtual Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent); + + virtual Error get_data(uint8_t* p_buffer, int p_bytes); + virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); + + void set_socket(int p_sockfd, IP_Address p_host, int p_port); + + virtual IP_Address get_connected_host() const; + virtual uint16_t get_connected_port() const; + + virtual bool is_connected() const; + virtual Status get_status() const; + virtual void disconnect(); + + static void make_default(); + static void cleanup(); + + virtual void set_nodelay(bool p_enabled); + + + StreamPeerWinsock(); + ~StreamPeerWinsock(); +}; + +#endif // TCP_SOCKET_POSIX_H + +#endif diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp new file mode 100644 index 0000000000..7b35bcc7ad --- /dev/null +++ b/platform/windows/tcp_server_winsock.cpp @@ -0,0 +1,166 @@ +/*************************************************************************/ +/* tcp_server_winsock.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "tcp_server_winsock.h"
+
+#include "stream_peer_winsock.h"
+
+#include <winsock2.h>
+
+extern int winsock_refcount;
+
+TCP_Server* TCPServerWinsock::_create() {
+
+ return memnew(TCPServerWinsock);
+};
+
+void TCPServerWinsock::make_default() {
+
+ TCP_Server::_create = TCPServerWinsock::_create;
+
+ if (winsock_refcount == 0) {
+ WSADATA data;
+ WSAStartup(MAKEWORD(2,2), &data);
+ };
+ ++winsock_refcount;
+};
+
+void TCPServerWinsock::cleanup() {
+
+ --winsock_refcount;
+ if (winsock_refcount == 0) {
+
+ WSACleanup();
+ };
+};
+
+
+Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
+
+ int sockfd;
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED);
+
+ unsigned long par = 1;
+ if (ioctlsocket(sockfd, FIONBIO, &par)) {
+ perror("setting non-block mode");
+ stop();
+ return FAILED;
+ };
+
+ struct sockaddr_in my_addr;
+ my_addr.sin_family = AF_INET; // host byte order
+ my_addr.sin_port = htons(p_port); // short, network byte order
+ my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts
+ memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero);
+
+ if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != SOCKET_ERROR) {
+
+ if (::listen(sockfd, SOMAXCONN) == SOCKET_ERROR) {
+
+ closesocket(sockfd);
+ ERR_FAIL_V(FAILED);
+ };
+ };
+
+ if (listen_sockfd != INVALID_SOCKET) {
+
+ stop();
+ };
+
+ listen_sockfd = sockfd;
+
+ return OK;
+};
+
+bool TCPServerWinsock::is_connection_available() const {
+
+ if (listen_sockfd == -1) {
+ return false;
+ };
+
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ fd_set pfd;
+ FD_ZERO(&pfd);
+ FD_SET(listen_sockfd, &pfd);
+
+ int ret = select(listen_sockfd + 1, &pfd, NULL, NULL, &timeout);
+ ERR_FAIL_COND_V(ret < 0, 0);
+
+ if (ret && (FD_ISSET(listen_sockfd, &pfd))) {
+
+ return true;
+ };
+
+ return false;
+};
+
+
+Ref<StreamPeerTCP> TCPServerWinsock::take_connection() {
+
+ if (!is_connection_available()) {
+ return NULL;
+ };
+
+ struct sockaddr_in their_addr;
+ int sin_size = sizeof(their_addr);
+ int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size);
+ ERR_FAIL_COND_V(fd == INVALID_SOCKET, NULL);
+
+ Ref<StreamPeerWinsock> conn = memnew(StreamPeerWinsock);
+ IP_Address ip;
+ ip.host = (uint32_t)their_addr.sin_addr.s_addr;
+
+ conn->set_socket(fd, ip, ntohs(their_addr.sin_port));
+
+ return conn;
+};
+
+void TCPServerWinsock::stop() {
+
+ if (listen_sockfd != INVALID_SOCKET) {
+ closesocket(listen_sockfd);
+ };
+
+ listen_sockfd = -1;
+};
+
+
+TCPServerWinsock::TCPServerWinsock() {
+
+ listen_sockfd = INVALID_SOCKET;
+};
+
+TCPServerWinsock::~TCPServerWinsock() {
+
+ stop();
+};
+
diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h new file mode 100644 index 0000000000..2d54b6ce40 --- /dev/null +++ b/platform/windows/tcp_server_winsock.h @@ -0,0 +1,55 @@ +/*************************************************************************/ +/* tcp_server_winsock.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef TCP_SERVER_WINSOCK_H
+#define TCP_SERVER_WINSOCK_H
+
+#include "core/io/tcp_server.h"
+
+class TCPServerWinsock : public TCP_Server {
+
+ int listen_sockfd;
+
+ static TCP_Server* _create();
+
+public:
+
+ virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
+ virtual bool is_connection_available() const;
+ virtual Ref<StreamPeerTCP> take_connection();
+
+ virtual void stop(); //stop listening
+
+ static void make_default();
+ static void cleanup();
+
+ TCPServerWinsock();
+ ~TCPServerWinsock();
+};
+
+#endif
|