minime.py (17141B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\minime.py 2 import sys 3 import ctypes 4 import ctypes.wintypes 5 import blue 6 import geo2 7 import time 8 import logmodule 9 try: 10 import trinity 11 except (ImportError, RuntimeError): 12 pass 13 14 WNDPROC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_long, ctypes.c_int, ctypes.c_int, ctypes.c_int) 15 16 def LOWORD(dword): 17 return dword & 65535 18 19 20 def HIWORD(dword): 21 return dword >> 16 22 23 24 hwnd = None 25 wndclass = None 26 OnKeyDown = None 27 OnKeyUp = None 28 OnChar = None 29 OnMouse = None 30 blueArgs = blue.pyos.GetArg()[1:] 31 32 def GetMousePosition(lparam): 33 x = LOWORD(lparam) 34 y = HIWORD(lparam) 35 return (x, y) 36 37 38 def PostOnMouse(event, wParam, lParam): 39 try: 40 if OnMouse is not None and callable(OnMouse): 41 x, y = GetMousePosition(lParam) 42 if event == 'MOUSE_WHEEL': 43 OnMouse(event, (x, y, HIWORD(wParam))) 44 else: 45 OnMouse(event, (x, y)) 46 except: 47 import traceback 48 traceback.print_exc() 49 50 51 class Camera(object): 52 53 def __init__(self, fov, front, back, asp): 54 self.minZoomDistance = 0.05 55 self.maxZoomDistance = 100000.0 56 self.parentPos = (0.0, 0.0, 0.0) 57 self.localViewMatrix = geo2.MatrixIdentity() 58 self.view = trinity.TriView() 59 self.view.transform = geo2.MatrixIdentity() 60 self.projection = trinity.TriProjection() 61 self.SetPerspective(fov, front, back, asp) 62 self.SetPosition((0.0, 50.0, -100.0)) 63 self.Focus((0.0, 0.0, 0.0)) 64 65 def _SetViewMatrix(self, value): 66 self.view.transform = value 67 68 def _GetViewMatrix(self): 69 return self.view.transform 70 71 viewMatrix = property(_GetViewMatrix, _SetViewMatrix) 72 73 def _GetProjectionMatrix(self): 74 return self.projection.transform 75 76 projectionMatrix = property(_GetProjectionMatrix) 77 78 def SetPerspective(self, fov, front, back, asp): 79 self.fieldOfView = fov 80 self.frontClip = front 81 self.backClip = back 82 self.aspectRatio = asp 83 self.projection.PerspectiveFov(self.fieldOfView, self.aspectRatio, self.frontClip, self.backClip) 84 85 def Update(self): 86 parentMat = geo2.MatrixTranslation(*self.parentPos) 87 viewInv = geo2.MatrixInverse(self.localViewMatrix) 88 newT = geo2.MatrixMultiply(viewInv, parentMat) 89 self.viewMatrix = geo2.MatrixInverse(newT) 90 trinity.SetViewTransform(self.viewMatrix) 91 trinity.SetPerspectiveProjection(self.fieldOfView, self.frontClip, self.backClip, self.aspectRatio) 92 self.projection.PerspectiveFov(self.fieldOfView, self.aspectRatio, self.frontClip, self.backClip) 93 94 def SetParentPos(self, pos): 95 self.parentPos = pos 96 97 def Zoom(self, val): 98 dev = trinity.device 99 pos = self.GetPosition() 100 target = self.GetPointOfInterest() 101 view = geo2.Vec3Normalize(geo2.Subtract(pos, target)) 102 length = geo2.Vec3Length(geo2.Subtract(pos, target)) 103 nextPos = geo2.Vec3Add(pos, geo2.Vec3Scale(view, length * val)) 104 nextLength = geo2.Vec3Length(geo2.Vec3Subtract(nextPos, target)) 105 if nextLength < self.minZoomDistance: 106 nextPos = geo2.Vec3Add(target, geo2.Vec3Scale(view, self.minZoomDistance)) 107 elif nextLength > self.maxZoomDistance: 108 nextPos = geo2.Vec3Add(target, geo2.Vec3Scale(view, self.maxZoomDistance)) 109 self.SetPosition(nextPos) 110 111 def Orbit(self, yaw, pitch): 112 dev = trinity.device 113 self.Focus(self.pointOfInterest) 114 up = geo2.Vector(0.0, 1.0, 0.0) 115 t = geo2.Vector(self.localViewMatrix[1][0], self.localViewMatrix[1][1], self.localViewMatrix[1][2]) 116 if geo2.Vec3Dot(t, up) <= 0.0: 117 pitch = -pitch 118 yaw = -yaw 119 pos = self.GetPosition() 120 target = self.pointOfInterest 121 view = geo2.Subtract(pos, target) 122 view = geo2.Vec3Normalize(view) 123 right = geo2.Vec3Cross(view, up) 124 mat = self.localViewMatrix 125 ipmat = geo2.MatrixTranslation(-target[0], -target[1], -target[2]) 126 pmat = geo2.MatrixTranslation(target[0], target[1], target[2]) 127 mat = geo2.MatrixInverse(mat) 128 yrotMat = geo2.MatrixRotationAxis(up, yaw) 129 rrotMat = geo2.MatrixRotationAxis(right, pitch) 130 yrotMat = geo2.MatrixMultiply(yrotMat, rrotMat) 131 mat = geo2.MatrixMultiply(mat, ipmat) 132 mat = geo2.MatrixMultiply(mat, yrotMat) 133 mat = geo2.MatrixMultiply(mat, pmat) 134 self._position = geo2.MatrixDecompose(mat)[2] 135 mat = geo2.MatrixInverse(mat) 136 self.localViewMatrix = mat 137 138 def Focus(self, point, dist = -1.0): 139 dev = trinity.device 140 pos = self.GetPosition() 141 up = (0.0, 1.0, 0.0) 142 t = (self.localViewMatrix[1][0], self.localViewMatrix[1][1], self.localViewMatrix[1][2]) 143 if geo2.Vec3Dot(t, up) <= 0.0: 144 up = (0.0, -1.0, 0.0) 145 self.pointOfInterest = point 146 self.localViewMatrix = geo2.MatrixLookAtRH(pos, point, up) 147 if dist > 0.0: 148 view = geo2.Vec3Subtract(pos, point) 149 view = geo2.Vec3Normalize(view) 150 self.SetPosition(geo2.Vec3Add(point, geo2.Vec3Scale(view, dist))) 151 152 def Pan(self, diff): 153 pos = self.GetPosition() 154 self.SetPosition(geo2.Vec3Add(pos, diff)) 155 self.pointOfInterest = geo2.Vec3Add(self.pointOfInterest, diff) 156 157 def SetPosition(self, pos): 158 mat = geo2.MatrixInverse(self.localViewMatrix) 159 mat = (mat[0], 160 mat[1], 161 mat[2], 162 (pos[0], 163 pos[1], 164 pos[2], 165 mat[3][3])) 166 self.localViewMatrix = geo2.MatrixInverse(mat) 167 self._position = pos 168 169 def GetPosition(self): 170 return self._position 171 172 def GetPointOfInterest(self): 173 return self.pointOfInterest 174 175 176 CS_HREDRAW = 2 177 CS_VREDRAW = 1 178 NULL = 0 179 IDI_APPLICATION = 32512 180 IDC_ARROW = 32512 181 WHITE_BRUSH = 0 182 BLACK_BRUSH = 4 183 WS_OVERLAPPEDWINDOW = 13565952 184 CW_USEDEFAULT = -2147483648L 185 SW_SHOWNORMAL = 1 186 WM_PAINT = 15 187 DT_SINGLELINE = 32 188 DT_CENTER = 1 189 DT_VCENTER = 4 190 WM_DESTROY = 2 191 GWL_STYLE = -16 192 WS_POPUP = -2147483648L 193 WS_SYSMENU = 524288 194 WS_VISIBLE = 268435456 195 WS_MINIMIZEBOX = 131072 196 WS_CAPTION = 12582912 197 WM_CLOSE = 16 198 WM_QUIT = 18 199 WM_SIZE = 5 200 WM_SETCURSOR = 32 201 WM_MOUSEFIRST = 512 202 WM_MOUSEMOVE = 512 203 WM_LBUTTONDOWN = 513 204 WM_LBUTTONUP = 514 205 WM_LBUTTONDBLCLK = 515 206 WM_RBUTTONDOWN = 516 207 WM_RBUTTONUP = 517 208 WM_RBUTTONDBLCLK = 518 209 WM_MBUTTONDOWN = 519 210 WM_MBUTTONUP = 520 211 WM_MBUTTONDBLCLK = 521 212 WM_MOUSEWHEEL = 522 213 WM_ACTIVATE = 6 214 WM_SYSCOMMAND = 274 215 WM_ERASEBKGND = 20 216 SC_KEYMENU = 61696 217 WA_ACTIVE = 1 218 WA_CLICKACTIVE = 2 219 WS_EX_TOPMOST = 8 220 WS_EX_COMPOSITED = 33554432 221 WM_KEYDOWN = 256 222 WM_KEYUP = 257 223 WM_CHAR = 258 224 WM_NCLBUTTONDOWN = 161 225 HTCAPTION = 2 226 WS_THICKFRAME = 262144 227 WS_SIZEBOX = WS_THICKFRAME 228 VK_RETURN = 13 229 VK_SHIFT = 16 230 VK_CONTROL = 17 231 VK_ESCAPE = 27 232 VK_SPACE = 32 233 VK_PRIOR = 33 234 VK_NEXT = 34 235 VK_END = 35 236 VK_HOME = 36 237 VK_LEFT = 37 238 VK_UP = 38 239 VK_RIGHT = 39 240 VK_DOWN = 40 241 VK_SELECT = 41 242 VK_PRINT = 42 243 VK_EXECUTE = 43 244 VK_SNAPSHOT = 44 245 VK_INSERT = 45 246 VK_DELETE = 46 247 VK_HELP = 47 248 SWP_NOSIZE = 1 249 SWP_NOMOVE = 2 250 SWP_NOZORDER = 4 251 WT_DEFAULT_FRAME = WS_OVERLAPPEDWINDOW 252 WT_FRAME_NO_X = WS_POPUP | WS_SIZEBOX 253 WT_NO_FRAME = WS_EX_TOPMOST | WS_POPUP 254 uilib = None 255 256 def SetWindowSize(w, h): 257 dev = trinity.device 258 hwnd = dev.GetWindow() 259 ctypes.windll.user32.SetWindowPos(ctypes.c_int(hwnd), 0, 0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE) 260 261 262 def SetWindowPos(x, y): 263 dev = trinity.device 264 hwnd = dev.GetWindow() 265 ctypes.windll.user32.SetWindowPos(ctypes.c_int(hwnd), 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE) 266 267 268 def StartUI(): 269 global uilib 270 from carbonui.uilib import Uilib 271 uilib = Uilib() 272 273 274 class WNDCLASS(ctypes.Structure): 275 _fields_ = [('style', ctypes.c_uint), 276 ('lpfnWndProc', WNDPROC), 277 ('cbClsExtra', ctypes.c_int), 278 ('cbWndExtra', ctypes.c_int), 279 ('hInstance', ctypes.wintypes.HINSTANCE), 280 ('hIcon', ctypes.wintypes.HICON), 281 ('hCursor', ctypes.wintypes.HICON), 282 ('hbrBackground', ctypes.wintypes.HBRUSH), 283 ('lpszMenuName', ctypes.wintypes.LPCSTR), 284 ('lpszClassName', ctypes.wintypes.LPCSTR)] 285 286 287 class RECT(ctypes.Structure): 288 _fields_ = [('left', ctypes.c_long), 289 ('top', ctypes.c_long), 290 ('right', ctypes.c_long), 291 ('bottom', ctypes.c_long)] 292 293 294 class PAINTSTRUCT(ctypes.Structure): 295 _fields_ = [('hdc', ctypes.c_int), 296 ('fErase', ctypes.c_int), 297 ('rcPaint', RECT), 298 ('fRestore', ctypes.c_int), 299 ('fIncUpdate', ctypes.c_int), 300 ('rgbReserved', ctypes.c_char * 32)] 301 302 303 class MARGINS(ctypes.Structure): 304 _fields_ = [('cxLeftWidth', ctypes.c_long), 305 ('cxRightWidth', ctypes.c_long), 306 ('cyTopHeight', ctypes.c_long), 307 ('cyBottomHeight', ctypes.c_long)] 308 309 310 class POINT(ctypes.Structure): 311 _fields_ = [('x', ctypes.c_long), ('y', ctypes.c_long)] 312 313 314 class MSG(ctypes.Structure): 315 _fields_ = [('hwnd', ctypes.c_int), 316 ('message', ctypes.c_uint), 317 ('wParam', ctypes.c_int), 318 ('lParam', ctypes.c_int), 319 ('time', ctypes.c_int), 320 ('pt', POINT)] 321 322 323 def ErrorIfZero(handle): 324 if handle == 0: 325 raise ctypes.WinError() 326 else: 327 return handle 328 329 330 def SetConstantYawRotation(rad_per_sec): 331 global START_TIME 332 START_TIME = time.clock() 333 334 def render_cb(): 335 global START_TIME 336 current = time.clock() 337 m = geo2.MatrixRotationY((current - START_TIME) * rad_per_sec) 338 trinity.SetViewTransform(geo2.MatrixMultiply(m, trinity.GetViewTransform())) 339 START_TIME = current 340 341 rj = trinity.CreateRenderJob('ConstantYawRotation') 342 rj.PythonCB(render_cb) 343 rj.ScheduleRecurring() 344 345 346 def CreateWindow(fullscreen = False, size = None, windowType = WT_DEFAULT_FRAME, showWindow = True): 347 global hwnd 348 global wndclass 349 CreateWindowEx = ctypes.windll.user32.CreateWindowExA 350 CreateWindowEx.argtypes = [ctypes.wintypes.DWORD, 351 ctypes.wintypes.LPCSTR, 352 ctypes.wintypes.LPCSTR, 353 ctypes.wintypes.DWORD, 354 ctypes.c_int, 355 ctypes.c_int, 356 ctypes.c_int, 357 ctypes.c_int, 358 ctypes.wintypes.HWND, 359 ctypes.wintypes.HMENU, 360 ctypes.wintypes.HINSTANCE, 361 ctypes.wintypes.LPVOID] 362 CreateWindowEx.restype = ErrorIfZero 363 wndclass = WNDCLASS() 364 wndclass.style = CS_HREDRAW | CS_VREDRAW 365 wndclass.lpfnWndProc = WNDPROC(WndProc) 366 wndclass.cbClsExtra = wndclass.cbWndExtra = 0 367 wndclass.hInstance = ctypes.windll.kernel32.GetModuleHandleA(ctypes.c_char_p(NULL)) 368 wndclass.hIcon = ctypes.windll.user32.LoadImageA(ctypes.c_void_p(NULL), ctypes.c_char_p(IDI_APPLICATION), ctypes.c_uint(1), ctypes.c_int64(10), ctypes.c_int64(10), ctypes.c_uint64(0)) 369 wndclass.hCursor = ctypes.windll.user32.LoadImageA(ctypes.c_void_p(NULL), ctypes.c_char_p(IDC_ARROW), ctypes.c_uint(2), ctypes.c_int64(10), ctypes.c_int64(10), ctypes.c_uint64(0)) 370 wndclass.hbrBackground = ctypes.windll.gdi32.GetStockObject(ctypes.c_int(BLACK_BRUSH)) 371 wndclass.lpszMenuName = None 372 wndclass.lpszClassName = 'MainWin' 373 if not ctypes.windll.user32.RegisterClassA(ctypes.byref(wndclass)): 374 raise ctypes.WinError() 375 if '/fullscreen' in blueArgs: 376 fullscreen = True 377 if fullscreen: 378 dspmode = trinity.adapters.GetCurrentDisplayMode(trinity.adapters.DEFAULT_ADAPTER) 379 if size is None: 380 width = dspmode.width 381 height = dspmode.height 382 else: 383 width, height = size 384 hwnd = CreateWindowEx(0, wndclass.lpszClassName, 'MINI ME', WS_EX_TOPMOST | WS_POPUP, 0, 0, width, height, NULL, NULL, wndclass.hInstance, NULL) 385 else: 386 if size is None: 387 width = CW_USEDEFAULT 388 height = CW_USEDEFAULT 389 else: 390 width, height = size 391 hwnd = CreateWindowEx(WS_EX_COMPOSITED, wndclass.lpszClassName, 'MINI ME', windowType, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, wndclass.hInstance, NULL) 392 if showWindow: 393 ctypes.windll.user32.ShowWindow(ctypes.c_int(hwnd), ctypes.c_int(SW_SHOWNORMAL)) 394 ctypes.windll.user32.UpdateWindow(ctypes.c_int(hwnd)) 395 return hwnd 396 397 398 def GetWindowSize(hwnd): 399 rect = RECT() 400 ctypes.windll.user32.GetClientRect(hwnd, ctypes.byref(rect)) 401 return (rect.right, rect.bottom) 402 403 404 def CreateDevice(hwnd, fullscreen = False): 405 if '/fullscreen' in blueArgs: 406 fullscreen = True 407 w, h = GetWindowSize(hwnd) 408 if fullscreen: 409 trinity.device.CreateFullScreenDevice(hwnd, w, h) 410 else: 411 trinity.device.CreateWindowedDevice(hwnd, w, h) 412 413 414 def RunTestScript(): 415 try: 416 for each in blueArgs: 417 if each.startswith('/test_script'): 418 path = each.split('=')[1] 419 execfile(path, globals()) 420 421 except Exception as e: 422 import traceback 423 traceback.print_exc() 424 logmodule.LogException() 425 sys.exc_clear() 426 427 428 def Main(postCreateCallback = None, fullscreen = False, size = None, windowType = WT_DEFAULT_FRAME): 429 hwnd = CreateWindow(fullscreen, size, windowType) 430 CreateDevice(hwnd, fullscreen) 431 w, h = GetWindowSize(hwnd) 432 asp = float(w) / float(h) 433 trinity.SetPerspectiveProjection(1.57, 1.0, 1000.0, asp) 434 if postCreateCallback and callable(postCreateCallback): 435 postCreateCallback() 436 MinimeMainLoop() 437 438 439 def MinimeMainLoop(): 440 msg = MSG() 441 pMsg = ctypes.pointer(msg) 442 running = True 443 TranslateMessage = ctypes.windll.user32.TranslateMessage 444 DispatchMessageA = ctypes.windll.user32.DispatchMessageA 445 PeekMessageA = ctypes.windll.user32.PeekMessageA 446 while running: 447 while PeekMessageA(pMsg, NULL, 0, 0, 1): 448 if msg.message == WM_QUIT: 449 running = False 450 break 451 TranslateMessage(pMsg) 452 DispatchMessageA(pMsg) 453 454 blue.os.Pump() 455 456 ctypes.windll.user32.PostQuitMessage(0) 457 return msg.wParam 458 459 460 def WndProc(hwnd, message, wParam, lParam): 461 dev = trinity.device 462 if message == WM_DESTROY: 463 blue.os.Terminate() 464 return 0 465 elif message == WM_CLOSE: 466 blue.os.Terminate() 467 return 0 468 if message == WM_SIZE: 469 if dev.GetWindow(): 470 rect = RECT() 471 ctypes.windll.user32.GetClientRect(hwnd, ctypes.byref(rect)) 472 viewTrans = trinity.GetViewTransform() 473 fov = trinity.GetFieldOfView() 474 front = trinity.GetFrontClip() 475 back = trinity.GetBackClip() 476 w, h = rect.right, rect.bottom 477 defaultBackBuffer = trinity.device.GetRenderContext().GetDefaultBackBuffer() 478 if w == defaultBackBuffer.width and h == defaultBackBuffer.height: 479 return 0 480 asp = float(w) / float(h) 481 dev.ChangeBackBufferSize(w, h) 482 trinity.SetPerspectiveProjection(fov, front, back, asp) 483 trinity.SetViewTransform(viewTrans) 484 elif message == WM_LBUTTONDOWN: 485 rect = RECT() 486 ctypes.windll.user32.GetClientRect(hwnd, ctypes.byref(rect)) 487 offset = POINT() 488 ctypes.windll.user32.ClientToScreen(hwnd, ctypes.byref(offset)) 489 ctypes.windll.user32.OffsetRect(ctypes.byref(rect), offset.x, offset.y) 490 ctypes.windll.user32.ClipCursor(ctypes.byref(rect)) 491 PostOnMouse('LEFT_BUTTON_DOWN', wParam, lParam) 492 elif message == WM_LBUTTONUP: 493 ctypes.windll.user32.ClipCursor(0) 494 PostOnMouse('LEFT_BUTTON_UP', wParam, lParam) 495 elif message == WM_LBUTTONDBLCLK: 496 PostOnMouse('LEFT_BUTTON_DBLCLK', wParam, lParam) 497 elif message == WM_RBUTTONUP: 498 PostOnMouse('RIGHT_BUTTON_UP', wParam, lParam) 499 elif message == WM_RBUTTONDOWN: 500 PostOnMouse('RIGHT_BUTTON_DOWN', wParam, lParam) 501 elif message == WM_RBUTTONDBLCLK: 502 PostOnMouse('RIGHT_BUTTON_DBLCLK', wParam, lParam) 503 elif message == WM_MBUTTONUP: 504 PostOnMouse('MIDDLE_BUTTON_UP', wParam, lParam) 505 elif message == WM_MBUTTONDOWN: 506 PostOnMouse('MIDDLE_BUTTON_DOWN', wParam, lParam) 507 elif message == WM_MBUTTONDBLCLK: 508 PostOnMouse('MIDDLE_BUTTON_DBLCLK', wParam, lParam) 509 elif message == WM_MOUSEMOVE: 510 PostOnMouse('MOUSE_MOVE', wParam, lParam) 511 elif message == WM_MOUSEWHEEL: 512 PostOnMouse('MOUSE_WHEEL', wParam, lParam) 513 elif message == WM_ACTIVATE: 514 if not (wParam == WA_ACTIVE and wParam == WA_CLICKACTIVE): 515 ctypes.windll.user32.ClipCursor(0) 516 elif message == WM_SYSCOMMAND: 517 if wParam == SC_KEYMENU: 518 return 0 519 else: 520 if message == WM_ERASEBKGND: 521 return 0 522 if message == WM_KEYDOWN: 523 if OnKeyDown is not None and callable(OnKeyDown): 524 OnKeyDown(wParam) 525 elif message == WM_KEYUP: 526 if OnKeyUp is not None and callable(OnKeyUp): 527 OnKeyUp(wParam) 528 elif message == WM_CHAR: 529 if OnChar is not None and callable(OnChar): 530 OnChar(wParam) 531 if uilib is not None: 532 return 0 533 else: 534 return ctypes.windll.user32.DefWindowProcA(ctypes.c_int(hwnd), ctypes.c_int(message), ctypes.c_int(wParam), ctypes.c_int(lParam))