1 // LDVLib.cpp : Defines the entry point for the DLL application.
2 //
3 
4 #include <LDLib/LDrawModelViewer.h>
5 #include <LDLib/LDPreferences.h>
6 #include <LDLoader/LDLModel.h>
7 #include <LDLib/LDInputHandler.h>
8 //#include <TCFoundation/TCAlert.h>
9 #include <TCFoundation/TCAlertManager.h>
10 #include <TCFoundation/TCUserDefaults.h>
11 #include <TRE/TREMainModel.h>
12 #include <TRE/TREGLExtensions.h>
13 #include "LDVLib.h"
14 #include "resource.h"
15 
16 struct ViewerInfo;
17 
18 class AlertHandler : public TCObject
19 {
20 public:
21 	AlertHandler(ViewerInfo *viewerInfo);
22 private:
23 	void captureAlertCallback(TCAlert *alert);
24 	void releaseAlertCallback(TCAlert *alert);
25 	void redrawAlertCallback(TCAlert *alert);
26 	void captureMouse(void);
27 	void releaseMouse(void);
28 
29 	ViewerInfo *m_viewerInfo;
30 };
31 
32 struct ViewerInfo
33 {
34 	LDrawModelViewer *modelViewer;
35 	HWND hwnd;
36 	HDC hdc;
37 	HWND hwndParent;
38 	HGLRC hglrc;
39 	int backgroundR;
40 	int backgroundG;
41 	int backgroundB;
42 	BOOL inputEnabled;
43 	AlertHandler *alertHandler;
44 };
45 
46 static HINSTANCE g_hModule;
47 static int g_initCount = 0;
48 ViewerInfo *g_sharedViewerInfo;
49 
50 #define OGL_WINDOW_CLASS_NAME "LDVLibOGLWindow"
51 #define REDRAW_TIMER 42
52 
53 #define waitForDebugger() \
54 	::MessageBox(NULL, "Attach Debugger", "DEBUG LDVLib.dll", MB_OK);
55 
DllMain(HANDLE hModule,DWORD,LPVOID)56 BOOL APIENTRY DllMain( HANDLE hModule,
57                        DWORD  /*ul_reason_for_call*/,
58                        LPVOID /*lpReserved*/
59 					 )
60 {
61 	g_hModule = (HINSTANCE)hModule;
62     return TRUE;
63 }
64 
getViewerInfo(void * pLDV)65 static ViewerInfo *getViewerInfo(void *pLDV)
66 {
67 	return (ViewerInfo *)pLDV;
68 }
69 
requestRedraw(HWND hWnd)70 static void requestRedraw(HWND hWnd)
71 {
72 	::SetTimer(hWnd, REDRAW_TIMER, 0, NULL);
73 }
74 
requestRedraw(void * pLDV)75 static void requestRedraw(void *pLDV)
76 {
77 	requestRedraw(getViewerInfo(pLDV)->hwnd);
78 }
79 
AlertHandler(ViewerInfo * viewerInfo)80 AlertHandler::AlertHandler(ViewerInfo *viewerInfo)
81 	: m_viewerInfo(viewerInfo)
82 {
83 	m_viewerInfo->alertHandler = this;
84 	TCAlertManager::registerHandler(LDInputHandler::captureAlertClass(), this,
85 		(TCAlertCallback)&AlertHandler::captureAlertCallback);
86 	TCAlertManager::registerHandler(LDInputHandler::releaseAlertClass(), this,
87 		(TCAlertCallback)&AlertHandler::releaseAlertCallback);
88 	TCAlertManager::registerHandler(LDrawModelViewer::redrawAlertClass(), this,
89 		(TCAlertCallback)&AlertHandler::redrawAlertCallback);
90 }
91 
captureMouse(void)92 void AlertHandler::captureMouse(void)
93 {
94 	SetCapture(m_viewerInfo->hwnd);
95 }
96 
releaseMouse(void)97 void AlertHandler::releaseMouse(void)
98 {
99 	ReleaseCapture();
100 }
101 
captureAlertCallback(TCAlert * alert)102 void AlertHandler::captureAlertCallback(TCAlert *alert)
103 {
104 	if (alert->getSender() == m_viewerInfo->modelViewer->getInputHandler())
105 	{
106 		captureMouse();
107 	}
108 }
109 
releaseAlertCallback(TCAlert * alert)110 void AlertHandler::releaseAlertCallback(TCAlert *alert)
111 {
112 	if (alert->getSender() == m_viewerInfo->modelViewer->getInputHandler())
113 	{
114 		releaseMouse();
115 	}
116 }
117 
redrawAlertCallback(TCAlert * alert)118 void AlertHandler::redrawAlertCallback(TCAlert *alert)
119 {
120 	if (alert->getSender() == m_viewerInfo->modelViewer)
121 	{
122 		requestRedraw(m_viewerInfo->hwnd);
123 	}
124 }
125 
getModelViewer(void * pLDV)126 static LDrawModelViewer *getModelViewer(void *pLDV)
127 {
128 	return getViewerInfo(pLDV)->modelViewer;
129 }
130 
makeCurrent(void * pLDV)131 static BOOL makeCurrent(void *pLDV)
132 {
133 	ViewerInfo *viewerInfo = getViewerInfo(pLDV);
134 	return wglMakeCurrent(viewerInfo->hdc, viewerInfo->hglrc);
135 }
136 
doPaint(ViewerInfo * viewerInfo,HWND hWnd)137 static LRESULT doPaint(ViewerInfo *viewerInfo, HWND hWnd)
138 {
139 	if (viewerInfo != NULL && viewerInfo->modelViewer != NULL)
140 	{
141 		PAINTSTRUCT paintStruct;
142 
143 		memset(&paintStruct, 0, sizeof(paintStruct));
144 		if (::BeginPaint(hWnd, &paintStruct))
145 		{
146 			makeCurrent(viewerInfo);
147 			viewerInfo->modelViewer->update();
148 			SwapBuffers(viewerInfo->hdc);
149 			::EndPaint(hWnd, &paintStruct);
150 		}
151 		return 0;
152 	}
153 	return DefWindowProc(hWnd, WM_PAINT, 0, 0);
154 }
155 
doEraseBackground(ViewerInfo * viewerInfo,HWND hWnd,HDC hdc)156 static LRESULT doEraseBackground(ViewerInfo *viewerInfo, HWND hWnd, HDC hdc)
157 {
158 	int r = 0;
159 	int g = 0;
160 	int b = 0;
161 
162 	if (viewerInfo != NULL)
163 	{
164 		r = viewerInfo->backgroundR;
165 		g = viewerInfo->backgroundG;
166 		b = viewerInfo->backgroundB;
167 	}
168 	HBRUSH hBgBrush = ::CreateSolidBrush(RGB(r, g, b));
169 	RECT updateRect;
170 	::GetUpdateRect(hWnd, &updateRect, FALSE);
171 	::FillRect(hdc, &updateRect, hBgBrush);
172 	::DeleteObject(hBgBrush);
173 	return 1;
174 }
175 
redraw(void * pLDV)176 static void redraw(void *pLDV)
177 {
178 	::RedrawWindow(getViewerInfo(pLDV)->hwnd, NULL, NULL,
179 		RDW_ERASE | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW);
180 }
181 
doTimer(ViewerInfo * viewerInfo,HWND hWnd,WPARAM timerID)182 static LRESULT doTimer(ViewerInfo *viewerInfo, HWND hWnd, WPARAM timerID)
183 {
184 	if (timerID == REDRAW_TIMER)
185 	{
186 		::KillTimer(hWnd, timerID);
187 		redraw(viewerInfo);
188 	}
189 	return 0;
190 }
191 
convertKeyModifiers(WPARAM osModifiers)192 static TCULong convertKeyModifiers(WPARAM osModifiers)
193 {
194 	TCULong retValue = 0;
195 
196 	if (osModifiers & MK_SHIFT)
197 	{
198 		retValue |= LDInputHandler::MKShift;
199 	}
200 	if (osModifiers & MK_CONTROL)
201 	{
202 		retValue |= LDInputHandler::MKControl;
203 	}
204 	return retValue;
205 }
206 
doButtonDown(ViewerInfo * viewerInfo,HWND hWnd,LDInputHandler::MouseButton button,WPARAM keyFlags,int xPos,int yPos)207 static LRESULT doButtonDown(
208 	ViewerInfo *viewerInfo,
209 	HWND hWnd,
210 	LDInputHandler::MouseButton button,
211 	WPARAM keyFlags,
212 	int xPos,
213 	int yPos)
214 {
215 	if (viewerInfo->inputEnabled &&
216 		viewerInfo->modelViewer->getInputHandler()->mouseDown(
217 		convertKeyModifiers(keyFlags), button, xPos, yPos))
218 	{
219 		requestRedraw(hWnd);
220 		::SetFocus(hWnd);
221 		return 0;
222 	}
223 	return 1;
224 }
225 
doButtonUp(ViewerInfo * viewerInfo,HWND hWnd,LDInputHandler::MouseButton button,WPARAM keyFlags,int xPos,int yPos)226 static LRESULT doButtonUp(
227 	ViewerInfo *viewerInfo,
228 	HWND hWnd,
229 	LDInputHandler::MouseButton button,
230 	WPARAM keyFlags,
231 	int xPos,
232 	int yPos)
233 {
234 	if (viewerInfo->inputEnabled &&
235 		viewerInfo->modelViewer->getInputHandler()->mouseUp(
236 		convertKeyModifiers(keyFlags), button, xPos, yPos))
237 	{
238 		requestRedraw(hWnd);
239 		return 0;
240 	}
241 	return 1;
242 }
243 
doMouseMove(ViewerInfo * viewerInfo,HWND hWnd,WPARAM keyFlags,int xPos,int yPos)244 static LRESULT doMouseMove(
245 	ViewerInfo *viewerInfo,
246 	HWND hWnd,
247 	WPARAM keyFlags,
248 	int xPos,
249 	int yPos)
250 {
251 	if (viewerInfo->inputEnabled &&
252 		viewerInfo->modelViewer->getInputHandler()->mouseMove(
253 		convertKeyModifiers(keyFlags), xPos, yPos))
254 	{
255 		requestRedraw(hWnd);
256 		return 0;
257 	}
258 	return 1;
259 }
260 
doMouseWheel(ViewerInfo * viewerInfo,HWND,short keyFlags,short zDelta,int,int)261 static LRESULT doMouseWheel(
262 	ViewerInfo *viewerInfo,
263 	HWND /*hWnd*/,
264 	short keyFlags,
265 	short zDelta,
266 	int /*xPos*/,
267 	int /*yPos*/)
268 {
269 	if (viewerInfo->inputEnabled)
270 	{
271 		viewerInfo->modelViewer->getInputHandler()->mouseWheel(
272 			convertKeyModifiers(keyFlags), (TCFloat)zDelta);
273 	}
274 	return 0;
275 }
276 
doSetFocus(ViewerInfo *,HWND,HWND)277 static LRESULT doSetFocus(
278 	ViewerInfo * /*viewerInfo*/,
279 	HWND /*hWnd*/,
280 	HWND /*hPrev*/)
281 {
282 	return 0;
283 }
284 
285 
staticWindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)286 static LRESULT CALLBACK staticWindowProc(
287 	HWND hWnd,
288 	UINT message,
289 	WPARAM wParam,
290 	LPARAM lParam)
291 {
292 #pragma warning(push)
293 #pragma warning(disable:4312)
294 	ViewerInfo *viewerInfo =
295 		(ViewerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
296 #pragma warning(pop)
297 
298 	switch (message)
299 	{
300 	case WM_CREATE:
301 	case WM_NCCREATE:
302 		{
303 			if (viewerInfo == NULL)
304 			{
305 				CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam;
306 
307 				viewerInfo = (ViewerInfo *)createStruct->lpCreateParams;
308 				if (viewerInfo != NULL)
309 				{
310 #pragma warning(push)
311 #pragma warning(disable:4244)
312 					SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)viewerInfo);
313 #pragma warning(pop)
314 					viewerInfo->hdc = ::GetDC(hWnd);
315 				}
316 			}
317 		}
318 		break;
319 	case WM_PAINT:
320 		return doPaint(viewerInfo, hWnd);
321 	case WM_TIMER:
322 		if (lParam == 0)
323 		{
324 			return doTimer(viewerInfo, hWnd, wParam);
325 		}
326 		break;
327 	case WM_ERASEBKGND:
328 		return doEraseBackground(viewerInfo, hWnd, (HDC)wParam);
329 	case WM_LBUTTONDOWN:
330 		return doButtonDown(viewerInfo, hWnd, LDInputHandler::MBLeft, wParam,
331 			(short)LOWORD(lParam), (short)HIWORD(lParam));
332 	case WM_LBUTTONUP:
333 		return doButtonUp(viewerInfo, hWnd, LDInputHandler::MBLeft, wParam,
334 			(short)LOWORD(lParam), (short)HIWORD(lParam));
335 	case WM_RBUTTONDOWN:
336 		return doButtonDown(viewerInfo, hWnd, LDInputHandler::MBRight, wParam,
337 			(short)LOWORD(lParam), (short)HIWORD(lParam));
338 	case WM_RBUTTONUP:
339 		return doButtonUp(viewerInfo, hWnd, LDInputHandler::MBRight, wParam,
340 			(short)LOWORD(lParam), (short)HIWORD(lParam));
341 	case WM_MBUTTONDOWN:
342 		return doButtonDown(viewerInfo, hWnd, LDInputHandler::MBMiddle, wParam,
343 			(short)LOWORD(lParam), (short)HIWORD(lParam));
344 	case WM_MBUTTONUP:
345 		return doButtonUp(viewerInfo, hWnd, LDInputHandler::MBMiddle, wParam,
346 			(short)LOWORD(lParam), (short)HIWORD(lParam));
347 	case WM_MOUSEMOVE:
348 		return doMouseMove(viewerInfo, hWnd, wParam, (short)LOWORD(lParam),
349 			(short)HIWORD(lParam));
350 	case WM_MOUSEWHEEL:
351 		return doMouseWheel(viewerInfo, hWnd, LOWORD(wParam), HIWORD(wParam),
352 			(short)LOWORD(lParam), (short)HIWORD(lParam));
353 	case WM_SETFOCUS:
354 		return doSetFocus(viewerInfo, hWnd, (HWND)wParam);
355 	}
356 	return DefWindowProc(hWnd, message, wParam, lParam);
357 }
358 
registerClass(void)359 static void registerClass(void)
360 {
361 	WNDCLASSEX windowClass;
362 
363 	memset(&windowClass, 0, sizeof(windowClass));
364 	// Set up and window class
365 	windowClass.cbSize = sizeof(windowClass);
366 	windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
367 	windowClass.lpfnWndProc = staticWindowProc;
368 	windowClass.cbClsExtra = 0;
369 	windowClass.cbWndExtra = 0;
370 	windowClass.hInstance = g_hModule;
371 	windowClass.hIcon = NULL;
372 	windowClass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
373 	windowClass.hbrBackground = NULL;
374 	windowClass.lpszMenuName = NULL;
375 	windowClass.lpszClassName = OGL_WINDOW_CLASS_NAME;
376 	windowClass.hIconSm = NULL;
377 	::RegisterClassEx(&windowClass);
378 }
379 
LDVInit(HWND hwnd)380 void *LDVInit(HWND hwnd)
381 {
382 	ViewerInfo *viewerInfo = new ViewerInfo;
383 	RECT clientRect;
384 	HRSRC hFontResource = FindResource(g_hModule,
385 		MAKEINTRESOURCE(IDR_SANS_FONT), RT_RCDATA);
386 
387 	if (++g_initCount == 1)
388 	{
389 		HRSRC hStudLogoResource = FindResource(g_hModule,
390 			MAKEINTRESOURCE(IDR_STUDLOGO_PNG), RT_RCDATA);
391 
392 		if (hStudLogoResource)
393 		{
394 			HGLOBAL hStudLogo = LoadResource(g_hModule, hStudLogoResource);
395 
396 			if (hStudLogo)
397 			{
398 				TCByte *data = (TCByte *)LockResource(hStudLogo);
399 
400 				if (data)
401 				{
402 					DWORD length = SizeofResource(g_hModule, hStudLogoResource);
403 
404 					if (length)
405 					{
406 						TREMainModel::setStudTextureData(data, length);
407 					}
408 				}
409 			}
410 		}
411 		registerClass();
412 		g_sharedViewerInfo = new ViewerInfo;
413 		memset(g_sharedViewerInfo, 0, sizeof(*g_sharedViewerInfo));
414 		g_sharedViewerInfo->hwndParent = NULL;
415 		g_sharedViewerInfo->hwnd = ::CreateWindowEx(
416 			0, OGL_WINDOW_CLASS_NAME, "LDVLib Window",
417 			WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
418 			0, 0, 320, 240, hwnd, NULL, g_hModule, g_sharedViewerInfo);
419 		LDVGLInit(g_sharedViewerInfo);
420 	}
421 	memset(viewerInfo, 0, sizeof(*viewerInfo));
422 	viewerInfo->inputEnabled = TRUE;
423 	viewerInfo->hwndParent = hwnd;
424 	::GetClientRect(hwnd, &clientRect);
425 	int width = clientRect.right - clientRect.left;
426 	int height = clientRect.bottom - clientRect.top;
427 	viewerInfo->hwnd = ::CreateWindowEx(
428 		0, OGL_WINDOW_CLASS_NAME, "LDVLib Window",
429 		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
430 		0, 0, width, height, hwnd, NULL, g_hModule, viewerInfo);
431 	viewerInfo->modelViewer = new LDrawModelViewer(width, height);
432 	LDPreferences *prefs = new LDPreferences(viewerInfo->modelViewer);
433 	prefs->loadSettings();
434 	prefs->applySettings();
435 	prefs->release();
436 	if (hFontResource)
437 	{
438 		HGLOBAL hFont = LoadResource(g_hModule, hFontResource);
439 
440 		if (hFont)
441 		{
442 			TCByte *data = (TCByte *)LockResource(hFont);
443 
444 			if (data)
445 			{
446 				DWORD length = SizeofResource(g_hModule, hFontResource);
447 
448 				if (length)
449 				{
450 					viewerInfo->modelViewer->setFontData(data, length);
451 				}
452 			}
453 		}
454 	}
455 	new AlertHandler(viewerInfo);
456 	return viewerInfo;
457 }
458 
SetRegistryAppName(const char * appName)459 void SetRegistryAppName(const char *appName)
460 {
461 	LDVSetRegistryAppName(appName);
462 }
463 
LDVSetRegistryAppName(const char * appName)464 void LDVSetRegistryAppName(const char *appName)
465 {
466 	TCUserDefaults::setAppName(appName);
467 }
468 
LDVSetCommandLine(const char * commandLine)469 void LDVSetCommandLine(const char *commandLine)
470 {
471 	TCUserDefaults::setCommandLine(commandLine);
472 }
473 
GLDeInit(ViewerInfo * viewerInfo)474 static void GLDeInit(ViewerInfo *viewerInfo)
475 {
476 	if (viewerInfo->hglrc != NULL)
477 	{
478 		wglMakeCurrent(NULL, NULL);
479 		wglDeleteContext(viewerInfo->hglrc);
480 		viewerInfo->hglrc = NULL;
481 	}
482 }
483 
setPixelFormat(HDC hdc,int pfIndex)484 static BOOL setPixelFormat(HDC hdc, int pfIndex)
485 {
486 	PIXELFORMATDESCRIPTOR pfd;
487 
488 	memset(&pfd, 0, sizeof(pfd));
489 	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
490 	pfd.nVersion = 1;
491 	if (SetPixelFormat(hdc, pfIndex, &pfd))
492 	{
493 		return TRUE;
494 	}
495 	return FALSE;
496 }
497 
setupPFD(ViewerInfo * viewerInfo)498 static BOOL setupPFD(ViewerInfo *viewerInfo)
499 {
500 	PIXELFORMATDESCRIPTOR pfd;
501 	BOOL retValue = FALSE;
502 
503 	memset(&pfd, 0, sizeof(pfd));
504 	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
505 	pfd.nVersion = 1;
506 	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER |
507 		PFD_GENERIC_ACCELERATED;
508 	pfd.iPixelType = PFD_TYPE_RGBA;
509 	pfd.cColorBits = 12;
510 	pfd.cDepthBits = 32;
511 	pfd.cStencilBits = 1;
512 	pfd.cAlphaBits = 4;
513 	int pfIndex = ChoosePixelFormat(viewerInfo->hdc, &pfd);
514 	if (pfIndex == 0)
515 	{ // Try with dest alpha but no stencil
516 		pfd.cStencilBits = 0;
517 		pfIndex = ChoosePixelFormat(viewerInfo->hdc, &pfd);
518 	}
519 	if (pfIndex == 0)
520 	{ // Try with stencil but no dest alpha
521 		pfd.cStencilBits = 1;
522 		pfd.cAlphaBits = 0;
523 		pfIndex = ChoosePixelFormat(viewerInfo->hdc, &pfd);
524 	}
525 	if (pfIndex == 0)
526 	{ // Try with no stencil OR dest alpha
527 		pfd.cStencilBits = 0;
528 		pfIndex = ChoosePixelFormat(viewerInfo->hdc, &pfd);
529 	}
530 	if (pfIndex != 0)
531 	{
532 		retValue = setPixelFormat(viewerInfo->hdc, pfIndex);
533 	}
534 	return retValue;
535 }
536 
LDVGLInit(void * pLDV)537 BOOL LDVGLInit(void *pLDV)
538 {
539 	BOOL retValue = FALSE;
540 	ViewerInfo *viewerInfo = getViewerInfo(pLDV);
541 	GLDeInit(viewerInfo);
542 	if (setupPFD(viewerInfo))
543 	{
544 		viewerInfo->hglrc = wglCreateContext(viewerInfo->hdc);
545 		if (viewerInfo->hglrc != NULL)
546 		{
547 			retValue = wglMakeCurrent(viewerInfo->hdc, viewerInfo->hglrc);
548 			if (retValue)
549 			{
550 				if (pLDV == g_sharedViewerInfo)
551 				{
552 					TREGLExtensions::setup();
553 				}
554 				else
555 				{
556 					wglShareLists(g_sharedViewerInfo->hglrc, viewerInfo->hglrc);
557 					glDrawBuffer(GL_BACK);
558 				}
559 			}
560 		}
561 	}
562 	return retValue;
563 }
564 
LDVDeInit(void * pLDV)565 void LDVDeInit(void *pLDV)
566 {
567 	GLDeInit(getViewerInfo(pLDV));
568 	TCObject::release(getViewerInfo(pLDV)->alertHandler);
569 	TCObject::release(getModelViewer(pLDV));
570 	if (--g_initCount == 0)
571 	{
572 		::UnregisterClass(OGL_WINDOW_CLASS_NAME, g_hModule);
573 	}
574 }
575 
LDVSetSize(void * pLDV,int width,int height)576 void LDVSetSize(void *pLDV, int width, int height)
577 {
578 	ViewerInfo *viewerInfo = getViewerInfo(pLDV);
579 
580 	::MoveWindow(viewerInfo->hwnd, 0, 0, width, height, FALSE);
581 	makeCurrent(pLDV);
582 	glViewport(0, 0, width, height);
583 	viewerInfo->modelViewer->setWidth(width);
584 	viewerInfo->modelViewer->setHeight(height);
585 	redraw(pLDV);
586 }
587 
LDVGetWidth(void * pLDV)588 int LDVGetWidth(void *pLDV)
589 {
590 	return getModelViewer(pLDV)->getWidth();
591 }
592 
LDVSetHeight(void * pLDV,int height)593 void LDVSetHeight(void *pLDV, int height)
594 {
595 	getModelViewer(pLDV)->setHeight(height);
596 }
597 
LDVGetHeight(void * pLDV)598 int LDVGetHeight(void *pLDV)
599 {
600 	return getModelViewer(pLDV)->getHeight();
601 }
602 
LDVSetFilename(void * pLDV,const char * filename)603 void LDVSetFilename(void *pLDV, const char *filename)
604 {
605 	getModelViewer(pLDV)->setFilename(filename);
606 }
607 
608 
chDirFromFilename(const char * filename,char * outFilename)609 static bool chDirFromFilename(const char* filename, char* outFilename)
610 {
611 	char buf[MAX_PATH];
612 	char* fileSpot;
613 	DWORD result = GetFullPathName(filename, MAX_PATH, buf, &fileSpot);
614 
615 	if (result <= MAX_PATH && result > 0)
616 	{
617 //		if (strlen(fileSpot) < strlen(filename))
618 		{
619 			strcpy(outFilename, buf);
620 		}
621 		*fileSpot = 0;
622 		if (SetCurrentDirectory(buf))
623 		{
624 			return true;
625 		}
626 	}
627 	return false;
628 }
629 
LDVLoadModel(void * pLDV,BOOL resetViewpoint)630 BOOL LDVLoadModel(void *pLDV, BOOL resetViewpoint)
631 {
632 	BOOL retValue = FALSE;
633 	if (makeCurrent(pLDV))
634 	{
635 		LDrawModelViewer *modelViewer = getModelViewer(pLDV);
636 		char origDir[1024];
637 		char fullPath[1024];
638 		bool dirChanged;
639 
640 		GetCurrentDirectory(sizeof(origDir), origDir);
641 		dirChanged = chDirFromFilename(modelViewer->getFilename(),
642 			fullPath);
643 		if (dirChanged)
644 		{
645 			modelViewer->setFilename(fullPath);
646 		}
647 		if (modelViewer->loadModel(resetViewpoint ? true : false))
648 		{
649 			redraw(pLDV);
650 			retValue = TRUE;
651 		}
652 		if (dirChanged)
653 		{
654 			SetCurrentDirectory(origDir);
655 		}
656 	}
657 	return retValue;
658 }
659 
LDVUpdate(void * pLDV)660 void LDVUpdate(void *pLDV)
661 {
662 	requestRedraw(pLDV);
663 }
664 
LDVSetBackgroundRGB(void * pLDV,int r,int g,int b)665 void LDVSetBackgroundRGB(void *pLDV, int r, int g, int b)
666 {
667 	ViewerInfo *viewerInfo = getViewerInfo(pLDV);
668 
669 	viewerInfo->backgroundR = r;
670 	viewerInfo->backgroundG = g;
671 	viewerInfo->backgroundB = b;
672 	getModelViewer(pLDV)->setBackgroundRGB(r, g, b);
673 	requestRedraw(pLDV);
674 }
675 
LDVGetBackgroundRGB(void * pLDV,int * r,int * g,int * b)676 void LDVGetBackgroundRGB(void *pLDV, int *r, int *g, int *b)
677 {
678 	ViewerInfo *viewerInfo = getViewerInfo(pLDV);
679 
680 	*r = viewerInfo->backgroundR;
681 	*g = viewerInfo->backgroundG;
682 	*b = viewerInfo->backgroundB;
683 }
684 
LDVSetDefaultRGB(void * pLDV,int r,int g,int b,BOOL transparent)685 void LDVSetDefaultRGB(void *pLDV, int r, int g, int b, BOOL transparent)
686 {
687 	getModelViewer(pLDV)->setDefaultRGB(r, g, b, transparent ? true : false);
688 	requestRedraw(pLDV);
689 }
690 
LDVGetDefaultRGB(void * pLDV,int * r,int * g,int * b,BOOL * transparent)691 void LDVGetDefaultRGB(void *pLDV, int *r, int *g, int *b, BOOL *transparent)
692 {
693 	TCByte rTemp, gTemp, bTemp;
694 	bool transTemp;
695 
696 	getModelViewer(pLDV)->getDefaultRGB(rTemp, gTemp, bTemp, transTemp);
697 	*r = rTemp;
698 	*g = gTemp;
699 	*b = bTemp;
700 	*transparent = transTemp ? TRUE : FALSE;
701 }
702 
LDVSetLDrawDir(const char * path)703 void LDVSetLDrawDir(const char *path)
704 {
705 	LDLModel::setLDrawDir(path);
706 }
707 
LDVResetView(void * pLDV,LDVViewingAngle viewingAngle)708 void LDVResetView(void *pLDV, LDVViewingAngle viewingAngle)
709 {
710 	getModelViewer(pLDV)->resetView((LDVAngle)viewingAngle);
711 	requestRedraw(pLDV);
712 }
713 
LDVEnableInput(void * pLDV,BOOL enable)714 void LDVEnableInput(void *pLDV, BOOL enable)
715 {
716 	getViewerInfo(pLDV)->inputEnabled = enable;
717 }
718 
LDVIsInputEnabled(void * pLDV)719 BOOL LDVIsInputEnabled(void *pLDV)
720 {
721 	return getViewerInfo(pLDV)->inputEnabled;
722 }
723 
LDVZoomToFit(void * pLDV)724 void LDVZoomToFit(void *pLDV)
725 {
726 	getModelViewer(pLDV)->zoomToFit();
727 	requestRedraw(pLDV);
728 }
729 
LDVHasFocus(void * pLDV)730 BOOL LDVHasFocus(void *pLDV)
731 {
732 	return getViewerInfo(pLDV)->hwnd == ::GetFocus();
733 }
734 
LDVGetUsesSpecular(void * pLDV)735 BOOL LDVGetUsesSpecular(void *pLDV)
736 {
737 	return getModelViewer(pLDV)->getUsesSpecular() != false;
738 }
739 
LDVSetUsesSpecular(void * pLDV,BOOL value)740 void LDVSetUsesSpecular(void *pLDV, BOOL value)
741 {
742 	getModelViewer(pLDV)->setUsesSpecular(value ? true : false);
743 	requestRedraw(pLDV);
744 }
745 
LDVGetSeamWidth(void * pLDV)746 float LDVGetSeamWidth(void *pLDV)
747 {
748 	return getModelViewer(pLDV)->getSeamWidth();
749 }
750 
LDVSetSeamWidth(void * pLDV,float value)751 void LDVSetSeamWidth(void *pLDV, float value)
752 {
753 	getModelViewer(pLDV)->setSeamWidth(value);
754 	requestRedraw(pLDV);
755 }
756 
LDVGetShowsEdges(void * pLDV)757 BOOL LDVGetShowsEdges(void *pLDV)
758 {
759 	return getModelViewer(pLDV)->getShowsHighlightLines() != false;
760 }
761 
LDVSetShowsEdges(void * pLDV,BOOL value)762 void LDVSetShowsEdges(void *pLDV, BOOL value)
763 {
764 	getModelViewer(pLDV)->setShowsHighlightLines(value ? true : false);
765 	requestRedraw(pLDV);
766 }
767 
LDVGetBlackEdges(void * pLDV)768 BOOL LDVGetBlackEdges(void *pLDV)
769 {
770 	return getModelViewer(pLDV)->getBlackHighlights() != false;
771 }
772 
LDVSetBlackEdges(void * pLDV,BOOL value)773 void LDVSetBlackEdges(void *pLDV, BOOL value)
774 {
775 	getModelViewer(pLDV)->setBlackHighlights(value ? true : false);
776 	requestRedraw(pLDV);
777 }
778 
LDVGetShowsConditionalEdges(void * pLDV)779 BOOL LDVGetShowsConditionalEdges(void *pLDV)
780 {
781 	return getModelViewer(pLDV)->getDrawConditionalHighlights() != false;
782 }
783 
LDVSetShowsConditionalEdges(void * pLDV,BOOL value)784 void LDVSetShowsConditionalEdges(void *pLDV, BOOL value)
785 {
786 	getModelViewer(pLDV)->setDrawConditionalHighlights(value ? true : false);
787 	requestRedraw(pLDV);
788 }
789 
LDVGetLowQualityStuds(void * pLDV)790 BOOL LDVGetLowQualityStuds(void *pLDV)
791 {
792 	return getModelViewer(pLDV)->getQualityStuds() == false;
793 }
794 
LDVSetLowQualityStuds(void * pLDV,BOOL value)795 void LDVSetLowQualityStuds(void *pLDV, BOOL value)
796 {
797 	getModelViewer(pLDV)->setQualityStuds(!value ? true : false);
798 	requestRedraw(pLDV);
799 }
800 
LDVGetLighting(void * pLDV)801 BOOL LDVGetLighting(void *pLDV)
802 {
803 	return getModelViewer(pLDV)->getUseLighting() != false;
804 }
805 
LDVSetLighting(void * pLDV,BOOL value)806 void LDVSetLighting(void *pLDV, BOOL value)
807 {
808 	getModelViewer(pLDV)->setUseLighting(value ? true : false);
809 	requestRedraw(pLDV);
810 }
811 
LDVGetSubduedLighting(void * pLDV)812 BOOL LDVGetSubduedLighting(void *pLDV)
813 {
814 	return getModelViewer(pLDV)->getSubduedLighting() != false;
815 }
816 
LDVSetSubduedLighting(void * pLDV,BOOL value)817 void LDVSetSubduedLighting(void *pLDV, BOOL value)
818 {
819 	getModelViewer(pLDV)->setSubduedLighting(value ? true : false);
820 	requestRedraw(pLDV);
821 }
822 
LDVGetTextureStuds(void * pLDV)823 BOOL LDVGetTextureStuds(void *pLDV)
824 {
825 	return getModelViewer(pLDV)->getTextureStuds() != false;
826 }
827 
LDVSetTextureStuds(void * pLDV,BOOL value)828 void LDVSetTextureStuds(void *pLDV, BOOL value)
829 {
830 	getModelViewer(pLDV)->setTextureStuds(value ? true : false);
831 	requestRedraw(pLDV);
832 }
833 
LDVGetTextureFilterType(void * pLDV)834 LDVTextureFilterType LDVGetTextureFilterType(void *pLDV)
835 {
836 	switch (getModelViewer(pLDV)->getTextureFilterType())
837 	{
838 	case GL_NEAREST_MIPMAP_NEAREST:
839 		return LDVTFTNearest;
840 	case GL_LINEAR_MIPMAP_NEAREST:
841 		return LDVTFTBilinear;
842 	case GL_LINEAR_MIPMAP_LINEAR:
843 		return LDVTFTTrilinear;
844 	default:
845 		return LDVTFTBilinear;
846 	}
847 }
848 
LDVSetTextureFilterType(void * pLDV,LDVTextureFilterType value)849 void LDVSetTextureFilterType(void *pLDV, LDVTextureFilterType value)
850 {
851 	int textureFilterType;
852 
853 	switch (value)
854 	{
855 	case LDVTFTNearest:
856 		textureFilterType = GL_NEAREST_MIPMAP_NEAREST;
857 		break;
858 	case LDVTFTTrilinear:
859 		textureFilterType = GL_LINEAR_MIPMAP_LINEAR;
860 		break;
861 	case LDVTFTBilinear:
862 	default:
863 		textureFilterType = GL_LINEAR_MIPMAP_NEAREST;
864 		break;
865 	}
866 	getModelViewer(pLDV)->setTextureFilterType(textureFilterType);
867 	requestRedraw(pLDV);
868 }
869 
LDVGetAnisoLevel(void * pLDV)870 float LDVGetAnisoLevel(void *pLDV)
871 {
872 	LDrawModelViewer *modelViewer = getModelViewer(pLDV);
873 
874 	if (modelViewer->getTextureFilterType() == GL_LINEAR_MIPMAP_LINEAR)
875 	{
876 		return modelViewer->getAnisoLevel();
877 	}
878 	else
879 	{
880 		return 1.0;
881 	}
882 }
883 
LDVSetAnisoLevel(void * pLDV,float value)884 void LDVSetAnisoLevel(void *pLDV, float value)
885 {
886 	LDrawModelViewer *modelViewer = getModelViewer(pLDV);
887 
888 	if (modelViewer->getTextureFilterType() != GL_LINEAR_MIPMAP_LINEAR)
889 	{
890 		value = 1.0;
891 	}
892 	modelViewer->setAnisoLevel(value);
893 	requestRedraw(pLDV);
894 }
895 
LDVGetMaxAnisoLevel(void)896 float LDVGetMaxAnisoLevel(void)
897 {
898 	return TREGLExtensions::getMaxAnisoLevel();
899 }
900 
LDVGetDrawWireframe(void * pLDV)901 BOOL LDVGetDrawWireframe(void *pLDV)
902 {
903 	return getModelViewer(pLDV)->getDrawWireframe() != false;
904 }
905 
LDVSetDrawWireframe(void * pLDV,BOOL value)906 void LDVSetDrawWireframe(void *pLDV, BOOL value)
907 {
908 	getModelViewer(pLDV)->setDrawWireframe(value ? true : false);
909 	requestRedraw(pLDV);
910 }
911 
LDVGetWireframeFog(void * pLDV)912 BOOL LDVGetWireframeFog(void *pLDV)
913 {
914 	return getModelViewer(pLDV)->getUseWireframeFog() != false;
915 }
916 
LDVSetWireframeFog(void * pLDV,BOOL value)917 void LDVSetWireframeFog(void *pLDV, BOOL value)
918 {
919 	getModelViewer(pLDV)->setUseWireframeFog(value ? true : false);
920 	requestRedraw(pLDV);
921 }
922 
LDVGetRemoveHiddenLines(void * pLDV)923 BOOL LDVGetRemoveHiddenLines(void *pLDV)
924 {
925 	return getModelViewer(pLDV)->getRemoveHiddenLines() != false;
926 }
927 
LDVSetRemoveHiddenLines(void * pLDV,BOOL value)928 void LDVSetRemoveHiddenLines(void *pLDV, BOOL value)
929 {
930 	getModelViewer(pLDV)->setRemoveHiddenLines(value ? true : false);
931 	requestRedraw(pLDV);
932 }
933 
LDVGetPrimitiveSubstitution(void * pLDV)934 BOOL LDVGetPrimitiveSubstitution(void *pLDV)
935 {
936 	return getModelViewer(pLDV)->getAllowPrimitiveSubstitution() != false;
937 }
938 
LDVSetPrimitiveSubstitution(void * pLDV,BOOL value)939 void LDVSetPrimitiveSubstitution(void *pLDV, BOOL value)
940 {
941 	getModelViewer(pLDV)->setAllowPrimitiveSubstitution(value ? true : false);
942 	requestRedraw(pLDV);
943 }
944 
LDVGetSmoothing(void * pLDV)945 BOOL LDVGetSmoothing(void *pLDV)
946 {
947 	return getModelViewer(pLDV)->getPerformSmoothing() != false;
948 }
949 
LDVSetSmoothing(void * pLDV,BOOL value)950 void LDVSetSmoothing(void *pLDV, BOOL value)
951 {
952 	getModelViewer(pLDV)->setPerformSmoothing(value ? true : false);
953 	requestRedraw(pLDV);
954 }
955 
LDVGetLineSmoothing(void * pLDV)956 BOOL LDVGetLineSmoothing(void *pLDV)
957 {
958 	return getModelViewer(pLDV)->getLineSmoothing() != false;
959 }
960 
LDVSetLineSmoothing(void * pLDV,BOOL value)961 void LDVSetLineSmoothing(void *pLDV, BOOL value)
962 {
963 	getModelViewer(pLDV)->setLineSmoothing(value ? true : false);
964 	requestRedraw(pLDV);
965 }
966 
LDVGetEdgesOnly(void * pLDV)967 BOOL LDVGetEdgesOnly(void *pLDV)
968 {
969 	return getModelViewer(pLDV)->getEdgesOnly() != false;
970 }
971 
LDVSetEdgesOnly(void * pLDV,BOOL value)972 void LDVSetEdgesOnly(void *pLDV, BOOL value)
973 {
974 	getModelViewer(pLDV)->setEdgesOnly(value ? true : false);
975 	requestRedraw(pLDV);
976 }
977 
LDVGetBFC(void * pLDV)978 BOOL LDVGetBFC(void *pLDV)
979 {
980 	return getModelViewer(pLDV)->getBfc() != false;
981 }
982 
LDVSetBFC(void * pLDV,BOOL value)983 void LDVSetBFC(void *pLDV, BOOL value)
984 {
985 	getModelViewer(pLDV)->setBfc(value ? true : false);
986 	requestRedraw(pLDV);
987 }
988 
LDVGetRedBackFaces(void * pLDV)989 BOOL LDVGetRedBackFaces(void *pLDV)
990 {
991 	return getModelViewer(pLDV)->getRedBackFaces() != false;
992 }
993 
LDVSetRedBackFaces(void * pLDV,BOOL value)994 void LDVSetRedBackFaces(void *pLDV, BOOL value)
995 {
996 	getModelViewer(pLDV)->setRedBackFaces(value ? true : false);
997 	requestRedraw(pLDV);
998 }
999 
LDVGetGreenFrontFaces(void * pLDV)1000 BOOL LDVGetGreenFrontFaces(void *pLDV)
1001 {
1002 	return getModelViewer(pLDV)->getGreenFrontFaces() != false;
1003 }
1004 
LDVSetGreenFrontFaces(void * pLDV,BOOL value)1005 void LDVSetGreenFrontFaces(void *pLDV, BOOL value)
1006 {
1007 	getModelViewer(pLDV)->setGreenFrontFaces(value ? true : false);
1008 	requestRedraw(pLDV);
1009 }
1010 
LDVGetBlueNeutralFaces(void * pLDV)1011 BOOL LDVGetBlueNeutralFaces(void *pLDV)
1012 {
1013 	return getModelViewer(pLDV)->getBlueNeutralFaces() != false;
1014 }
1015 
LDVSetBlueNeutralFaces(void * pLDV,BOOL value)1016 void LDVSetBlueNeutralFaces(void *pLDV, BOOL value)
1017 {
1018 	getModelViewer(pLDV)->setBlueNeutralFaces(value ? true : false);
1019 	requestRedraw(pLDV);
1020 }
1021 
LDVGetCheckPartsTracker(void * pLDV)1022 BOOL LDVGetCheckPartsTracker(void *pLDV)
1023 {
1024 	return getModelViewer(pLDV)->getCheckPartTracker() != false;
1025 }
1026 
LDVSetCheckPartsTracker(void * pLDV,BOOL value)1027 void LDVSetCheckPartsTracker(void *pLDV, BOOL value)
1028 {
1029 	getModelViewer(pLDV)->setCheckPartTracker(value ? true : false);
1030 	requestRedraw(pLDV);
1031 }
1032 
LDVGetShowsAxes(void * pLDV)1033 BOOL LDVGetShowsAxes(void *pLDV)
1034 {
1035 	return getModelViewer(pLDV)->getShowAxes() != false;
1036 }
1037 
LDVSetShowsAxes(void * pLDV,BOOL value)1038 void LDVSetShowsAxes(void *pLDV, BOOL value)
1039 {
1040 	getModelViewer(pLDV)->setShowAxes(value ? true : false);
1041 	requestRedraw(pLDV);
1042 }
1043 
LDVGetShowsBoundingBox(void * pLDV)1044 BOOL LDVGetShowsBoundingBox(void *pLDV)
1045 {
1046 	return getModelViewer(pLDV)->getShowBoundingBox() != false;
1047 }
1048 
LDVSetShowsBoundingBox(void * pLDV,BOOL value)1049 void LDVSetShowsBoundingBox(void *pLDV, BOOL value)
1050 {
1051 	getModelViewer(pLDV)->setShowBoundingBox(value ? true : false);
1052 	requestRedraw(pLDV);
1053 }
1054 
LDVGetBoundingBoxesOnly(void * pLDV)1055 BOOL LDVGetBoundingBoxesOnly(void *pLDV)
1056 {
1057 	return getModelViewer(pLDV)->getBoundingBoxesOnly() != false;
1058 }
1059 
LDVSetBoundingBoxesOnly(void * pLDV,BOOL value)1060 void LDVSetBoundingBoxesOnly(void *pLDV, BOOL value)
1061 {
1062 	getModelViewer(pLDV)->setBoundingBoxesOnly(value ? true : false);
1063 	requestRedraw(pLDV);
1064 }
1065 
LDVGetOBI(void * pLDV)1066 BOOL LDVGetOBI(void *pLDV)
1067 {
1068 	return getModelViewer(pLDV)->getObi() != false;
1069 }
1070 
LDVSetOBI(void * pLDV,BOOL value)1071 void LDVSetOBI(void *pLDV, BOOL value)
1072 {
1073 	getModelViewer(pLDV)->setObi(value ? true : false);
1074 	requestRedraw(pLDV);
1075 }
1076 
LDVGetRandomColors(void * pLDV)1077 BOOL LDVGetRandomColors(void *pLDV)
1078 {
1079 	return getModelViewer(pLDV)->getRandomColors() != false;
1080 }
1081 
LDVSetRandomColors(void * pLDV,BOOL value)1082 void LDVSetRandomColors(void *pLDV, BOOL value)
1083 {
1084 	getModelViewer(pLDV)->setRandomColors(value ? true : false);
1085 	requestRedraw(pLDV);
1086 }
1087 
LDVGetTexmaps(void * pLDV)1088 BOOL LDVGetTexmaps(void *pLDV)
1089 {
1090 	return getModelViewer(pLDV)->getTexmaps() != false;
1091 }
1092 
LDVSetTexmaps(void * pLDV,BOOL value)1093 void LDVSetTexmaps(void *pLDV, BOOL value)
1094 {
1095 	getModelViewer(pLDV)->setTexmaps(value ? true : false);
1096 	requestRedraw(pLDV);
1097 }
1098 
LDVGetFOV(void * pLDV)1099 float LDVGetFOV(void *pLDV)
1100 {
1101 	return getModelViewer(pLDV)->getFov();
1102 }
1103 
LDVSetFOV(void * pLDV,float value)1104 void LDVSetFOV(void *pLDV, float value)
1105 {
1106 	getModelViewer(pLDV)->setFov(value);
1107 	requestRedraw(pLDV);
1108 }
1109 
LDVGetShowsAllConditionalEdges(void * pLDV)1110 BOOL LDVGetShowsAllConditionalEdges(void *pLDV)
1111 {
1112 	return getModelViewer(pLDV)->getShowAllConditionalLines() != false;
1113 }
1114 
LDVSetShowsAllConditionalEdges(void * pLDV,BOOL value)1115 void LDVSetShowsAllConditionalEdges(void *pLDV, BOOL value)
1116 {
1117 	getModelViewer(pLDV)->setShowAllConditionalLines(value ? true : false);
1118 	requestRedraw(pLDV);
1119 }
1120