nuclear@73: #include <stdio.h>
nuclear@73: #include <string.h>
nuclear@73: #include <stdlib.h>
nuclear@73: #include <errno.h>
nuclear@73: #include <map>
nuclear@73: #include <windows.h>
nuclear@73: #include <shlobj.h>
nuclear@73: #include "max.h"
nuclear@73: #include "impexp.h"		// SceneExport
nuclear@73: #include "iparamb2.h"	// ClassDesc2
nuclear@73: #include "plugapi.h"
nuclear@73: #include "IGame.h"
nuclear@73: #include "IGameExport.h"
nuclear@73: #include "IConversionmanager.h"
nuclear@73: 
nuclear@73: 
nuclear@73: #pragma comment (lib, "core.lib")
nuclear@73: #pragma comment (lib, "geom.lib")
nuclear@73: #pragma comment (lib, "gfx.lib")
nuclear@73: #pragma comment (lib, "mesh.lib")
nuclear@73: #pragma comment (lib, "maxutil.lib")
nuclear@73: #pragma comment (lib, "maxscrpt.lib")
nuclear@73: #pragma comment (lib, "paramblk2.lib")
nuclear@73: #pragma comment (lib, "msxml2.lib")
nuclear@73: #pragma comment (lib, "igame.lib")
nuclear@73: #pragma comment (lib, "comctl32.lib")
nuclear@73: 
nuclear@73: 
nuclear@73: #define VER_MAJOR	1
nuclear@73: #define VER_MINOR	0
nuclear@73: #define VERSION(major, minor) \
nuclear@73: 	((major) * 100 + ((minor) < 10 ? (minor) * 10 : (minor)))
nuclear@73: 
nuclear@73: typedef int (*PluginInitFunc)();
nuclear@73: typedef int (*PluginShutdownFunc)();
nuclear@73: typedef ClassDesc *(*PluginClassDescFunc)(int);
nuclear@73: 
nuclear@73: static FILE *logfile;
nuclear@73: static HINSTANCE hinst;
nuclear@73: static const wchar_t *copyright_str = L"Copyright 2013 (C) John Tsiombikas - GNU General Public License v3, see COPYING for details.";
nuclear@73: 
nuclear@73: class GoatExporterStub : public SceneExport {
nuclear@73: public:
nuclear@73: 	IGameScene *igame;
nuclear@73: 
nuclear@73: 	int ExtCount() { return 1; }
nuclear@73: 	const TCHAR *Ext(int n) { return L"goatsce"; }
nuclear@73: 	const TCHAR *LongDesc() { return L"Goat3D Scene file"; }
nuclear@73: 	const TCHAR *ShortDesc() { return L"Goat3D Scene"; }
nuclear@73: 	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
nuclear@73: 	const TCHAR *CopyrightMessage() { return copyright_str; }
nuclear@73: 	const TCHAR *OtherMessage1() { return L"foo1"; }
nuclear@73: 	const TCHAR *OtherMessage2() { return L"foo2"; }
nuclear@73: 	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
nuclear@73: 	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D exporter", "About this plugin", 0); }
nuclear@73: 
nuclear@73: 	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
nuclear@73: };
nuclear@73: 
nuclear@73: class GoatAnimExporterStub : public SceneExport {
nuclear@73: public:
nuclear@73: 	IGameScene *igame;
nuclear@73: 
nuclear@73: 	int ExtCount() { return 1; }
nuclear@73: 	const TCHAR *Ext(int n) { return L"goatanm"; }
nuclear@73: 	const TCHAR *LongDesc() { return L"Goat3D Animation file"; }
nuclear@73: 	const TCHAR *ShortDesc() { return L"Goat3D Animation"; }
nuclear@73: 	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
nuclear@73: 	const TCHAR *CopyrightMessage() { return copyright_str; }
nuclear@73: 	const TCHAR *OtherMessage1() { return L"bar1"; }
nuclear@73: 	const TCHAR *OtherMessage2() { return L"bar2"; }
nuclear@73: 	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
nuclear@73: 	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D anim exporter", "About this plugin", 0); }
nuclear@73: 
nuclear@73: 	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
nuclear@73: };
nuclear@73: 
nuclear@73: static const char *find_dll_dir()
nuclear@73: {
nuclear@73: 	static char path[MAX_PATH];
nuclear@73: 
nuclear@73: 	HMODULE dll;
nuclear@73: 	if(!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
nuclear@73: 			(LPCSTR)find_dll_dir, &dll)) {
nuclear@73: 		return 0;
nuclear@73: 	}
nuclear@73: 	GetModuleFileNameA(dll, path, sizeof path);
nuclear@73: 
nuclear@73: 	char *last_slash = strrchr(path, '\\');
nuclear@73: 	if(last_slash && last_slash[1]) {
nuclear@73: 		*last_slash = 0;
nuclear@73: 	}
nuclear@73: 
nuclear@73: 	return path;
nuclear@73: }
nuclear@73: 
nuclear@73: static int do_export(int which, const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL non_int, DWORD opt)
nuclear@73: {
nuclear@73: 	const char *dll_fname = "maxgoat.dll";
nuclear@73: 	char *dll_path;
nuclear@73: 	HMODULE dll = 0;
nuclear@73: 	PluginInitFunc init;
nuclear@73: 	PluginShutdownFunc shutdown;
nuclear@73: 	PluginClassDescFunc get_class_desc;
nuclear@73: 	ClassDesc *desc;
nuclear@73: 	SceneExport *ex;
nuclear@73: 	int result = IMPEXP_FAIL;
nuclear@73: 
nuclear@73: 	const char *plugdir = find_dll_dir();
nuclear@73: 	if(plugdir) {
nuclear@73: 		dll_path = new char[strlen(dll_fname) + strlen(plugdir) + 2];
nuclear@73: 		sprintf(dll_path, "%s\\%s", plugdir, dll_fname);
nuclear@73: 	} else {
nuclear@73: 		dll_path = new char[strlen(dll_fname) + 1];
nuclear@73: 		strcpy(dll_path, dll_fname);
nuclear@73: 	}
nuclear@73: 
nuclear@73: 	if(!(dll = LoadLibraryA(dll_path))) {
nuclear@73: 		fprintf(logfile, "failed to load exporter: %s\n", dll_path);
nuclear@73: 		goto done;
nuclear@73: 	}
nuclear@73: 
nuclear@73: 	if(!(get_class_desc = (PluginClassDescFunc)GetProcAddress(dll, "LibClassDesc"))) {
nuclear@73: 		fprintf(logfile, "maxgoat.dll is invalid (no LibClassDesc function)\n");
nuclear@73: 		goto done;
nuclear@73: 	}
nuclear@73: 
nuclear@73: 	// first initialize the library
nuclear@73: 	if((init = (PluginInitFunc)GetProcAddress(dll, "LibInitialize"))) {
nuclear@73: 		if(!init()) {
nuclear@73: 			fprintf(logfile, "exporter initialization failed!\n");
nuclear@73: 			goto done;
nuclear@73: 		}
nuclear@73: 	}
nuclear@73: 
nuclear@73: 	if(!(desc = get_class_desc(which))) {
nuclear@73: 		fprintf(logfile, "failed to get the class descriptor\n");
nuclear@73: 		goto done;
nuclear@73: 	}
nuclear@73: 
nuclear@73: 	if(!(ex = (SceneExport*)desc->Create())) {
nuclear@73: 		fprintf(logfile, "failed to create exporter class instance\n");
nuclear@73: 		goto done;
nuclear@73: 	}
nuclear@73: 
nuclear@73: 	__try {
nuclear@73: 		result = ex->DoExport(name, eiface, iface);
nuclear@73: 	}
nuclear@73: 	__except(EXCEPTION_EXECUTE_HANDLER) {
nuclear@73: 		fprintf(logfile, "Exception caught!\n");
nuclear@73: 		delete ex;
nuclear@73: 		goto done;
nuclear@73: 	}
nuclear@73: 	delete ex;
nuclear@73: 
nuclear@73: 	if((shutdown = (PluginShutdownFunc)GetProcAddress(dll, "LibShutdown"))) {
nuclear@73: 		shutdown();
nuclear@73: 	}
nuclear@73: 
nuclear@73: done:
nuclear@73: 	delete [] dll_path;
nuclear@73: 	if(dll) {
nuclear@73: 		FreeLibrary(dll);
nuclear@73: 	}
nuclear@73: 	return result;
nuclear@73: }
nuclear@73: 
nuclear@73: int GoatExporterStub::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
nuclear@73: 		BOOL non_interactive, DWORD opt)
nuclear@73: {
nuclear@73: 	return do_export(0, name, eiface, iface, non_interactive, opt);
nuclear@73: }
nuclear@73: 
nuclear@73: 
nuclear@73: int GoatAnimExporterStub::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
nuclear@73: 		BOOL non_interactive, DWORD opt)
nuclear@73: {
nuclear@73: 	return do_export(1, name, eiface, iface, non_interactive, opt);
nuclear@73: }
nuclear@73: 
nuclear@73: // ------------------------------------------
nuclear@73: 
nuclear@73: class GoatClassDesc : public ClassDesc2 {
nuclear@73: public:
nuclear@73: 	int IsPublic() { return TRUE; }
nuclear@73: 	void *Create(BOOL loading = FALSE) { return new GoatExporterStub; }
nuclear@73: 	const TCHAR *ClassName() { return L"GoatExporterStub"; }
nuclear@73: 	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
nuclear@73: 	Class_ID ClassID() { return Class_ID(0x2e4e6311, 0x2b154d91); }
nuclear@73: 	const TCHAR *Category() { return L"Mutant Stargoat"; }
nuclear@73: 
nuclear@73: 	const TCHAR *InternalName() { return L"GoatExporterStub"; }
nuclear@73: 	HINSTANCE HInstance() { return hinst; }
nuclear@73: };
nuclear@73: 
nuclear@73: class GoatAnimClassDesc : public ClassDesc2 {
nuclear@73: public:
nuclear@73: 	int IsPublic() { return TRUE; }
nuclear@73: 	void *Create(BOOL loading = FALSE) { return new GoatAnimExporterStub; }
nuclear@73: 	const TCHAR *ClassName() { return L"GoatAnimExporterStub"; }
nuclear@73: 	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
nuclear@73: 	Class_ID ClassID() { return Class_ID(0x75054666, 0x45487285); }
nuclear@73: 	const TCHAR *Category() { return L"Mutant Stargoat"; }
nuclear@73: 
nuclear@73: 	const TCHAR *InternalName() { return L"GoatAnimExporterStub"; }
nuclear@73: 	HINSTANCE HInstance() { return hinst; }
nuclear@73: };
nuclear@73: 
nuclear@73: 
nuclear@73: static GoatClassDesc class_desc;
nuclear@73: static GoatAnimClassDesc anim_class_desc;
nuclear@73: 
nuclear@73: BOOL WINAPI DllMain(HINSTANCE inst_handle, ULONG reason, void *reserved)
nuclear@73: {
nuclear@73: 	if(reason == DLL_PROCESS_ATTACH) {
nuclear@73: 		hinst = inst_handle;
nuclear@73: 		DisableThreadLibraryCalls(hinst);
nuclear@73: 	}
nuclear@73: 	return TRUE;
nuclear@73: }
nuclear@73: 
nuclear@73: extern "C" {
nuclear@73: 
nuclear@73: __declspec(dllexport) const TCHAR *LibDescription()
nuclear@73: {
nuclear@73: 	return L"Goat3D exporter stub";
nuclear@73: }
nuclear@73: 
nuclear@73: __declspec(dllexport) int LibNumberClasses()
nuclear@73: {
nuclear@73: 	return 2;
nuclear@73: }
nuclear@73: 
nuclear@73: __declspec(dllexport) ClassDesc *LibClassDesc(int i)
nuclear@73: {
nuclear@73: 	switch(i) {
nuclear@73: 	case 0:
nuclear@73: 		return &class_desc;
nuclear@73: 	case 1:
nuclear@73: 		return &anim_class_desc;
nuclear@73: 	default:
nuclear@73: 		break;
nuclear@73: 	}
nuclear@73: 	return 0;
nuclear@73: }
nuclear@73: 
nuclear@73: __declspec(dllexport) ULONG LibVersion()
nuclear@73: {
nuclear@73: 	return Get3DSMAXVersion();
nuclear@73: }
nuclear@73: 
nuclear@73: __declspec(dllexport) int LibInitialize()
nuclear@73: {
nuclear@73: 	static char path[1024];
nuclear@73: 
nuclear@73: 	SHGetFolderPathA(0, CSIDL_PERSONAL, 0, 0, path);
nuclear@73: 	strcat(path, "/testexpstub.log");
nuclear@73: 
nuclear@73: 	if((logfile = fopen(path, "w"))) {
nuclear@73: 		setvbuf(logfile, 0, _IONBF, 0);
nuclear@73: 	}
nuclear@73: 	return TRUE;
nuclear@73: }
nuclear@73: 
nuclear@73: __declspec(dllexport) int LibShutdown()
nuclear@73: {
nuclear@73: 	if(logfile) {
nuclear@73: 		fclose(logfile);
nuclear@73: 		logfile = 0;
nuclear@73: 	}
nuclear@73: 	return TRUE;
nuclear@73: }
nuclear@73: 
nuclear@73: }	// extern "C"