goat3d

changeset 66:3751aabbc5b3

igame animation api is weird...
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 19 Apr 2014 07:56:43 +0300
parents cd7efb8757e1
children 8970ca3d55e0
files exporters/maxgoat/maxgoat.rc exporters/maxgoat/maxgoat.vcxproj exporters/maxgoat/maxgoat.vcxproj.filters exporters/maxgoat/resource.h exporters/maxgoat/src/maxgoat.cc exporters/maxgoat/src/minwin.cc exporters/maxgoat/src/minwin.h exporters/maxgoat_stub/maxgoat_stub.vcxproj exporters/maxgoat_stub/src/stub.cc goat3d.vcxproj src/goat3d.cc src/scene.cc src/xform_node.cc
diffstat 13 files changed, 209 insertions(+), 313 deletions(-) [+]
line diff
     1.1 Binary file exporters/maxgoat/maxgoat.rc has changed
     2.1 --- a/exporters/maxgoat/maxgoat.vcxproj	Tue Apr 01 13:11:04 2014 +0300
     2.2 +++ b/exporters/maxgoat/maxgoat.vcxproj	Sat Apr 19 07:56:43 2014 +0300
     2.3 @@ -33,7 +33,7 @@
     2.4    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     2.5      <ConfigurationType>DynamicLibrary</ConfigurationType>
     2.6      <UseDebugLibraries>true</UseDebugLibraries>
     2.7 -    <PlatformToolset>v100</PlatformToolset>
     2.8 +    <PlatformToolset>v110</PlatformToolset>
     2.9      <CharacterSet>Unicode</CharacterSet>
    2.10    </PropertyGroup>
    2.11    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    2.12 @@ -46,7 +46,7 @@
    2.13    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    2.14      <ConfigurationType>DynamicLibrary</ConfigurationType>
    2.15      <UseDebugLibraries>false</UseDebugLibraries>
    2.16 -    <PlatformToolset>v100</PlatformToolset>
    2.17 +    <PlatformToolset>v110</PlatformToolset>
    2.18      <WholeProgramOptimization>true</WholeProgramOptimization>
    2.19      <CharacterSet>Unicode</CharacterSet>
    2.20    </PropertyGroup>
    2.21 @@ -109,7 +109,7 @@
    2.22        <AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    2.23      </Link>
    2.24      <PostBuildEvent>
    2.25 -      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2014)plugins\$(TargetFileName)"</Command>
    2.26 +      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2015)plugins\$(TargetFileName)"</Command>
    2.27      </PostBuildEvent>
    2.28    </ItemDefinitionGroup>
    2.29    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    2.30 @@ -151,25 +151,22 @@
    2.31        <AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    2.32      </Link>
    2.33      <PostBuildEvent>
    2.34 -      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2014)plugins\$(TargetFileName)"</Command>
    2.35 +      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2015)plugins\$(TargetFileName)"</Command>
    2.36      </PostBuildEvent>
    2.37    </ItemDefinitionGroup>
    2.38    <ItemGroup>
    2.39      <ClCompile Include="src\logger.cc" />
    2.40      <ClCompile Include="src\maxgoat.cc" />
    2.41 -    <ClCompile Include="src\minwin.cc" />
    2.42    </ItemGroup>
    2.43    <ItemGroup>
    2.44      <ClInclude Include="resource.h" />
    2.45      <ClInclude Include="src\logger.h" />
    2.46 -    <ClInclude Include="src\minwin.h" />
    2.47    </ItemGroup>
    2.48    <ItemGroup>
    2.49      <ResourceCompile Include="maxgoat.rc" />
    2.50    </ItemGroup>
    2.51    <ItemGroup>
    2.52      <None Include="msglogo3d.bmp" />
    2.53 -    <None Include="msglogo3d.png" />
    2.54    </ItemGroup>
    2.55    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    2.56    <ImportGroup Label="ExtensionTargets">
     3.1 --- a/exporters/maxgoat/maxgoat.vcxproj.filters	Tue Apr 01 13:11:04 2014 +0300
     3.2 +++ b/exporters/maxgoat/maxgoat.vcxproj.filters	Sat Apr 19 07:56:43 2014 +0300
     3.3 @@ -10,17 +10,11 @@
     3.4      <ClCompile Include="src\maxgoat.cc">
     3.5        <Filter>src</Filter>
     3.6      </ClCompile>
     3.7 -    <ClCompile Include="src\minwin.cc">
     3.8 -      <Filter>src</Filter>
     3.9 -    </ClCompile>
    3.10      <ClCompile Include="src\logger.cc">
    3.11        <Filter>src</Filter>
    3.12      </ClCompile>
    3.13    </ItemGroup>
    3.14    <ItemGroup>
    3.15 -    <ClInclude Include="src\minwin.h">
    3.16 -      <Filter>src</Filter>
    3.17 -    </ClInclude>
    3.18      <ClInclude Include="src\logger.h">
    3.19        <Filter>src</Filter>
    3.20      </ClInclude>
    3.21 @@ -32,7 +26,6 @@
    3.22      <ResourceCompile Include="maxgoat.rc" />
    3.23    </ItemGroup>
    3.24    <ItemGroup>
    3.25 -    <None Include="msglogo3d.png" />
    3.26      <None Include="msglogo3d.bmp" />
    3.27    </ItemGroup>
    3.28  </Project>
    3.29 \ No newline at end of file
     4.1 Binary file exporters/maxgoat/resource.h has changed
     5.1 --- a/exporters/maxgoat/src/maxgoat.cc	Tue Apr 01 13:11:04 2014 +0300
     5.2 +++ b/exporters/maxgoat/src/maxgoat.cc	Sat Apr 19 07:56:43 2014 +0300
     5.3 @@ -1,6 +1,7 @@
     5.4  #include <stdio.h>
     5.5  #include <string.h>
     5.6  #include <stdlib.h>
     5.7 +#include <ctype.h>
     5.8  #include <errno.h>
     5.9  #include <map>
    5.10  #include <windows.h>
    5.11 @@ -11,9 +12,9 @@
    5.12  #include "plugapi.h"
    5.13  #include "IGame.h"
    5.14  #include "IGameExport.h"
    5.15 +#include "IGameControl.h"
    5.16  #include "IConversionmanager.h"
    5.17  #include "goat3d.h"
    5.18 -#include "minwin.h"
    5.19  #include "config.h"
    5.20  #include "logger.h"
    5.21  #include "resource.h"
    5.22 @@ -31,9 +32,15 @@
    5.23  #pragma comment (lib, "comctl32.lib")
    5.24  
    5.25  
    5.26 +#define COPYRIGHT	\
    5.27 +	L"Copyright 2014 (C) John Tsiombikas - GNU General Public License v3, see COPYING for details."
    5.28  #define VERSION(major, minor) \
    5.29  	((major) * 100 + ((minor) < 10 ? (minor) * 10 : (minor)))
    5.30  
    5.31 +static INT_PTR CALLBACK scene_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
    5.32 +static INT_PTR CALLBACK anim_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
    5.33 +static const char *max_string(const MCHAR *wstr);
    5.34 +
    5.35  HINSTANCE hinst;
    5.36  
    5.37  class GoatExporter : public SceneExport {
    5.38 @@ -44,17 +51,6 @@
    5.39  public:
    5.40  	IGameScene *igame;
    5.41  
    5.42 -	int ExtCount();
    5.43 -	const TCHAR *Ext(int n);
    5.44 -	const TCHAR *LongDesc();
    5.45 -	const TCHAR *ShortDesc();
    5.46 -	const TCHAR *AuthorName();
    5.47 -	const TCHAR *CopyrightMessage();
    5.48 -	const TCHAR *OtherMessage1();
    5.49 -	const TCHAR *OtherMessage2();
    5.50 -	unsigned int Version();
    5.51 -	void ShowAbout(HWND win);
    5.52 -
    5.53  	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
    5.54  
    5.55  	void process_materials(goat3d *goat);
    5.56 @@ -64,96 +60,36 @@
    5.57  	void process_mesh(goat3d *goat, goat3d_mesh *mesh, IGameObject *maxobj);
    5.58  	void process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj);
    5.59  	void process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj);
    5.60 +
    5.61 +
    5.62 +	int ExtCount() { return 1; }
    5.63 +	const TCHAR *Ext(int n) { return L"goatsce"; }
    5.64 +	const TCHAR *LongDesc() { return L"Goat3D scene file"; }
    5.65 +	const TCHAR *ShortDesc() { return L"Goat3D"; }
    5.66 +	const TCHAR *AuthorName() { return L"John Tsiombikas"; }
    5.67 +	const TCHAR *CopyrightMessage() { return COPYRIGHT; }
    5.68 +	const TCHAR *OtherMessage1() { return L"other1"; }
    5.69 +	const TCHAR *OtherMessage2() { return L"other2"; }
    5.70 +	unsigned int Version() { return VERSION(VER_MAJOR, VER_MINOR); }
    5.71 +	void ShowAbout(HWND win) { MessageBoxA(win, "Goat3D exporter plugin", "About this plugin", 0); }
    5.72  };
    5.73  
    5.74 +class GoatAnimExporter : public GoatExporter {
    5.75 +private:
    5.76 +public:
    5.77 +	int DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent = FALSE, DWORD opt = 0);
    5.78  
    5.79 -int GoatExporter::ExtCount()
    5.80 -{
    5.81 -	return 1;
    5.82 -}
    5.83 +	const TCHAR *Ext(int n) { return L"goatanm"; }
    5.84 +	const TCHAR *LongDesc() { return L"Goat3D animation file"; }
    5.85 +};
    5.86  
    5.87 -const TCHAR *GoatExporter::Ext(int n)
    5.88 -{
    5.89 -	return L"xml";
    5.90 -}
    5.91  
    5.92 -const TCHAR *GoatExporter::LongDesc()
    5.93 -{
    5.94 -	return L"Goat3D scene file";
    5.95 -}
    5.96 -
    5.97 -const TCHAR *GoatExporter::ShortDesc()
    5.98 -{
    5.99 -	return L"Goat3D";
   5.100 -}
   5.101 -
   5.102 -const TCHAR *GoatExporter::AuthorName()
   5.103 -{
   5.104 -	return L"John Tsiombikas";
   5.105 -}
   5.106 -
   5.107 -const TCHAR *GoatExporter::CopyrightMessage()
   5.108 -{
   5.109 -	return L"Copyright 2013 (C) John Tsiombikas - GNU General Public License v3, see COPYING for details.";
   5.110 -}
   5.111 -
   5.112 -const TCHAR *GoatExporter::OtherMessage1()
   5.113 -{
   5.114 -	return L"other1";
   5.115 -}
   5.116 -
   5.117 -const TCHAR *GoatExporter::OtherMessage2()
   5.118 -{
   5.119 -	return L"other2";
   5.120 -}
   5.121 -
   5.122 -unsigned int GoatExporter::Version()
   5.123 -{
   5.124 -	return VERSION(VER_MAJOR, VER_MINOR);
   5.125 -}
   5.126 -
   5.127 -void GoatExporter::ShowAbout(HWND win)
   5.128 -{
   5.129 -	MessageBoxA(win, "Goat3D exporter plugin", "About this plugin", 0);
   5.130 -}
   5.131 -
   5.132 -static INT_PTR CALLBACK handle_dlg_events(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
   5.133 -{
   5.134 -	switch(msg) {
   5.135 -	case WM_INITDIALOG:
   5.136 -		CheckDlgButton(win, IDC_GOAT_NODES, 1);
   5.137 -		CheckDlgButton(win, IDC_GOAT_MESHES, 1);
   5.138 -		CheckDlgButton(win, IDC_GOAT_LIGHTS, 1);
   5.139 -		CheckDlgButton(win, IDC_GOAT_CAMERAS, 1);
   5.140 -		break;
   5.141 -
   5.142 -	case WM_COMMAND:
   5.143 -		switch(LOWORD(wparam)) {
   5.144 -		case IDOK:
   5.145 -			EndDialog(win, 1);
   5.146 -			break;
   5.147 -
   5.148 -		case IDCANCEL:
   5.149 -			EndDialog(win, 0);
   5.150 -			break;
   5.151 -
   5.152 -		default:
   5.153 -			return 0;
   5.154 -		}
   5.155 -		break;
   5.156 -
   5.157 -	default:
   5.158 -		return 0;
   5.159 -	}
   5.160 -
   5.161 -	return 1;
   5.162 -}
   5.163 +// ---- GoatExporter implementation ----
   5.164  
   5.165  int GoatExporter::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface,
   5.166  		BOOL non_interactive, DWORD opt)
   5.167  {
   5.168 -	if(!DialogBox(hinst, MAKEINTRESOURCE(IDD_GOAT_SCE), 0, handle_dlg_events)) {
   5.169 -		maxlog("canceled!\n");
   5.170 +	if(!DialogBox(hinst, MAKEINTRESOURCE(IDD_GOAT_SCE), 0, scene_gui_handler)) {
   5.171  		return IMPEXP_CANCEL;
   5.172  	}
   5.173  
   5.174 @@ -162,6 +98,9 @@
   5.175  
   5.176  	char fname[512];
   5.177  	wcstombs(fname, name, sizeof fname - 1);
   5.178 +	for(int i=0; fname[i]; i++) {
   5.179 +		fname[i] = tolower(fname[i]);
   5.180 +	}
   5.181  
   5.182  	maxlog("Exporting Goat3D Scene (text) file: %s\n", fname);
   5.183  	if(!(igame = GetIGameInterface())) {
   5.184 @@ -171,7 +110,6 @@
   5.185  	IGameConversionManager *cm = GetConversionManager();
   5.186  	cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
   5.187  	igame->InitialiseIGame();
   5.188 -	igame->SetStaticFrame(0);
   5.189  
   5.190  	goat3d *goat = goat3d_create();
   5.191  
   5.192 @@ -192,14 +130,6 @@
   5.193  	return IMPEXP_SUCCESS;
   5.194  }
   5.195  
   5.196 -static const char *max_string(const MCHAR *wstr)
   5.197 -{
   5.198 -	if(!wstr) return 0;
   5.199 -	static char str[512];
   5.200 -	wcstombs(str, wstr, sizeof str - 1);
   5.201 -	return str;
   5.202 -}
   5.203 -
   5.204  void GoatExporter::process_materials(goat3d *goat)
   5.205  {
   5.206  	IGameProperty *prop;
   5.207 @@ -293,6 +223,10 @@
   5.208  	goat3d_node *node = goat3d_create_node();
   5.209  	goat3d_add_node(goat, node);
   5.210  
   5.211 +	if(parent) {
   5.212 +		goat3d_add_node_child(parent, node);
   5.213 +	}
   5.214 +
   5.215  	const char *name = max_string(maxnode->GetName());
   5.216  	if(name) {
   5.217  		goat3d_set_node_name(node, name);
   5.218 @@ -356,7 +290,19 @@
   5.219  		// otherwise don't assign an object, essentially treating it as a null node
   5.220  		break;
   5.221  	}
   5.222 -		
   5.223 +
   5.224 +	// grab the animation data
   5.225 +	IGameControl *ctrl = maxnode->GetIGameControl();
   5.226 +
   5.227 +	IGameKeyTab tm_keys;
   5.228 +	if(ctrl->GetFullSampledKeys(tm_keys, 1, IGAME_TM)) {
   5.229 +		maxlog("node: %s has %d keys\n", name, tm_keys.Count());
   5.230 +		/*for(int i=0; i<pkeys.Count(); i++) {
   5.231 +			Point3 p = pkeys[i].linearKey.pval;
   5.232 +			TimeValue t = pkeys[i].t;
   5.233 +			goat3d_set_node_position(node, p.x, p.y, p.z, TicksToSec(t));
   5.234 +		}*/
   5.235 +	}	
   5.236  
   5.237  	for(int i=0; i<maxnode->GetChildCount(); i++) {
   5.238  		process_node(goat, node, maxnode->GetNodeChild(i));
   5.239 @@ -424,12 +370,117 @@
   5.240  
   5.241  void GoatExporter::process_light(goat3d *goat, goat3d_light *light, IGameObject *maxobj)
   5.242  {
   5.243 +	// TODO
   5.244  }
   5.245  
   5.246  void GoatExporter::process_camera(goat3d *goat, goat3d_camera *cam, IGameObject *maxobj)
   5.247  {
   5.248 +	// TODO
   5.249  }
   5.250  
   5.251 +static INT_PTR CALLBACK scene_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
   5.252 +{
   5.253 +	switch(msg) {
   5.254 +	case WM_INITDIALOG:
   5.255 +		CheckDlgButton(win, IDC_GOAT_NODES, 1);
   5.256 +		CheckDlgButton(win, IDC_GOAT_MESHES, 1);
   5.257 +		CheckDlgButton(win, IDC_GOAT_LIGHTS, 1);
   5.258 +		CheckDlgButton(win, IDC_GOAT_CAMERAS, 1);
   5.259 +		break;
   5.260 +
   5.261 +	case WM_COMMAND:
   5.262 +		switch(LOWORD(wparam)) {
   5.263 +		case IDOK:
   5.264 +			EndDialog(win, 1);
   5.265 +			break;
   5.266 +
   5.267 +		case IDCANCEL:
   5.268 +			EndDialog(win, 0);
   5.269 +			break;
   5.270 +
   5.271 +		default:
   5.272 +			return 0;
   5.273 +		}
   5.274 +		break;
   5.275 +
   5.276 +	default:
   5.277 +		return 0;
   5.278 +	}
   5.279 +
   5.280 +	return 1;
   5.281 +}
   5.282 +
   5.283 +
   5.284 +
   5.285 +// ---- GoatAnimExporter implementation ----
   5.286 +
   5.287 +int GoatAnimExporter::DoExport(const MCHAR *name, ExpInterface *eiface, Interface *iface, BOOL silent, DWORD opt)
   5.288 +{
   5.289 +	if(!DialogBox(hinst, MAKEINTRESOURCE(IDD_GOAT_ANM), 0, anim_gui_handler)) {
   5.290 +		return IMPEXP_CANCEL;
   5.291 +	}
   5.292 +
   5.293 +	char fname[512];
   5.294 +	wcstombs(fname, name, sizeof fname - 1);
   5.295 +	for(int i=0; fname[i]; i++) {
   5.296 +		fname[i] = tolower(fname[i]);
   5.297 +	}
   5.298 +
   5.299 +	maxlog("Exporting Goat3D Animation (text) file: %s\n", fname);
   5.300 +	if(!(igame = GetIGameInterface())) {
   5.301 +		maxlog("failed to get the igame interface\n");
   5.302 +		return IMPEXP_FAIL;
   5.303 +	}
   5.304 +	IGameConversionManager *cm = GetConversionManager();
   5.305 +	cm->SetCoordSystem(IGameConversionManager::IGAME_OGL);
   5.306 +	igame->InitialiseIGame();
   5.307 +	igame->SetStaticFrame(0);
   5.308 +
   5.309 +	goat3d *goat = goat3d_create();
   5.310 +
   5.311 +	// process all nodes
   5.312 +	for(int i=0; i<igame->GetTopLevelNodeCount(); i++) {
   5.313 +		IGameNode *node = igame->GetTopLevelNode(i);
   5.314 +		process_node(goat, 0, node);
   5.315 +	}
   5.316 +
   5.317 +	if(goat3d_save_anim(goat, fname) == -1) {
   5.318 +		goat3d_free(goat);
   5.319 +		return IMPEXP_FAIL;
   5.320 +	}
   5.321 +
   5.322 +	goat3d_free(goat);
   5.323 +	return IMPEXP_SUCCESS;
   5.324 +}
   5.325 +
   5.326 +static INT_PTR CALLBACK anim_gui_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
   5.327 +{
   5.328 +	switch(msg) {
   5.329 +	case WM_INITDIALOG:
   5.330 +		CheckDlgButton(win, IDC_GOAT_ANM_FULL, 1);
   5.331 +		break;
   5.332 +
   5.333 +	case WM_COMMAND:
   5.334 +		switch(LOWORD(wparam)) {
   5.335 +		case IDOK:
   5.336 +			EndDialog(win, 1);
   5.337 +			break;
   5.338 +
   5.339 +		case IDCANCEL:
   5.340 +			EndDialog(win, 0);
   5.341 +			break;
   5.342 +
   5.343 +		default:
   5.344 +			return 0;
   5.345 +		}
   5.346 +		break;
   5.347 +
   5.348 +	default:
   5.349 +		return 0;
   5.350 +	}
   5.351 +
   5.352 +	return 1;
   5.353 +}
   5.354  
   5.355  // ------------------------------------------
   5.356  
   5.357 @@ -446,8 +497,22 @@
   5.358  	HINSTANCE HInstance() { return hinst; }
   5.359  };
   5.360  
   5.361 +class GoatAnimClassDesc : public ClassDesc2 {
   5.362 +public:
   5.363 +	int IsPublic() { return TRUE; }
   5.364 +	void *Create(BOOL loading = FALSE) { return new GoatAnimExporter; }
   5.365 +	const TCHAR *ClassName() { return L"GoatAnimExporter"; }
   5.366 +	SClass_ID SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   5.367 +	Class_ID ClassID() { return Class_ID(0x51b94924, 0x2e0332f3); }
   5.368 +	const TCHAR *Category() { return L"Mutant Stargoat"; }
   5.369 +
   5.370 +	const TCHAR *InternalName() { return L"GoatAnimExporter"; }
   5.371 +	HINSTANCE HInstance() { return hinst; }
   5.372 +};
   5.373 +
   5.374  // TODO: make 2 class descriptors, one for goat3d, one for goat3danim
   5.375  static GoatClassDesc class_desc;
   5.376 +static GoatAnimClassDesc anim_class_desc;
   5.377  
   5.378  BOOL WINAPI DllMain(HINSTANCE inst_handle, ULONG reason, void *reserved)
   5.379  {
   5.380 @@ -472,7 +537,15 @@
   5.381  
   5.382  __declspec(dllexport) ClassDesc *LibClassDesc(int i)
   5.383  {
   5.384 -	return i == 0 ? &class_desc : 0;
   5.385 +	switch(i) {
   5.386 +	case 0:
   5.387 +		return &class_desc;
   5.388 +	case 1:
   5.389 +		return &anim_class_desc;
   5.390 +	default:
   5.391 +		break;
   5.392 +	}
   5.393 +	return 0;
   5.394  }
   5.395  
   5.396  __declspec(dllexport) ULONG LibVersion()
   5.397 @@ -497,4 +570,13 @@
   5.398  	return TRUE;
   5.399  }
   5.400  
   5.401 -}	// extern "C"
   5.402 \ No newline at end of file
   5.403 +}	// extern "C"
   5.404 +
   5.405 +
   5.406 +static const char *max_string(const MCHAR *wstr)
   5.407 +{
   5.408 +	if(!wstr) return 0;
   5.409 +	static char str[512];
   5.410 +	wcstombs(str, wstr, sizeof str - 1);
   5.411 +	return str;
   5.412 +}
   5.413 \ No newline at end of file
     6.1 --- a/exporters/maxgoat/src/minwin.cc	Tue Apr 01 13:11:04 2014 +0300
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,170 +0,0 @@
     6.4 -#include <string.h>
     6.5 -#include <windows.h>
     6.6 -#include "minwin.h"
     6.7 -#include "logger.h"
     6.8 -
     6.9 -#define GOATSCE_WCLASS	"goatsce-window"
    6.10 -
    6.11 -struct MinWidget {
    6.12 -	HWND win;
    6.13 -
    6.14 -	MWCallback cbfunc;
    6.15 -	void *cbcls;
    6.16 -
    6.17 -	MinWidget() { win = 0; cbfunc = 0; cbcls = 0; }
    6.18 -};
    6.19 -
    6.20 -static void init();
    6.21 -static MinWidget *createwin(MinWidget *parent, const char *cls, const char *name,
    6.22 -		unsigned int style, int x, int y, int xsz, int ysz);
    6.23 -static LRESULT CALLBACK handle_msg(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam);
    6.24 -
    6.25 -extern HINSTANCE hinst;	// defined in maxgoat.cc
    6.26 -
    6.27 -void mw_set_callback(MinWidget *w, MWCallback func, void *cls)
    6.28 -{
    6.29 -	w->cbfunc = func;
    6.30 -	w->cbcls = cls;
    6.31 -}
    6.32 -
    6.33 -MinWidget *mw_create_window(MinWidget *parent, const char *name, int x, int y, int xsz, int ysz)
    6.34 -{
    6.35 -	unsigned int style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
    6.36 -	if(parent) {
    6.37 -		style |= WS_CHILD;
    6.38 -	}
    6.39 -
    6.40 -	maxlog("creating window: %s\n", name);
    6.41 -
    6.42 -	MinWidget *w = createwin(parent, GOATSCE_WCLASS, name, style, x, y, xsz, ysz);
    6.43 -	return w;
    6.44 -}
    6.45 -
    6.46 -MinWidget *mw_create_button(MinWidget *parent, const char *text, int x, int y, int xsz, int ysz)
    6.47 -{
    6.48 -	unsigned int style = BS_PUSHBUTTON | WS_VISIBLE;
    6.49 -	if(parent) {
    6.50 -		style |= WS_CHILD;
    6.51 -	}
    6.52 -
    6.53 -	maxlog("creating button: %s\n", text);
    6.54 -
    6.55 -	MinWidget *w = createwin(parent, "BUTTON", text, style, x, y, xsz, ysz);
    6.56 -	return w;
    6.57 -}
    6.58 -
    6.59 -MinWidget *mw_create_checkbox(MinWidget *parent, const char *text, int x, int y, int xsz, int ysz, bool checked)
    6.60 -{
    6.61 -	unsigned int style = BS_CHECKBOX | WS_VISIBLE;
    6.62 -	if(parent) {
    6.63 -		style |= WS_CHILD;
    6.64 -	}
    6.65 -
    6.66 -	maxlog("creating checkbox: %s\n", text);
    6.67 -
    6.68 -	MinWidget *w = createwin(parent, "CHECKBOX", text, style, x, y, xsz, ysz);
    6.69 -	return w;
    6.70 -}
    6.71 -
    6.72 -static DWORD WINAPI gui_thread_func(void *cls);
    6.73 -
    6.74 -void mw_test()
    6.75 -{
    6.76 -	init();
    6.77 -
    6.78 -	HANDLE thread = CreateThread(0, 0, gui_thread_func, 0, 0, 0);
    6.79 -	//WaitForSingleObject(thread, 5000);
    6.80 -}
    6.81 -
    6.82 -static DWORD WINAPI gui_thread_func(void *cls)
    6.83 -{
    6.84 -	MinWidget *win = mw_create_window(0, "test window!", -1, -1, 400, 400);
    6.85 -	MinWidget *bn_ok = mw_create_button(win, "Ok", 50, 100, 150, 40);
    6.86 -	MinWidget *bn_cancel = mw_create_button(win, "Cancel", 250, 100, 150, 40);
    6.87 -	MinWidget *ck_lights = mw_create_checkbox(win, "Export lights", 20, 20, 250, 40, true);
    6.88 -	MinWidget *ck_cameras = mw_create_checkbox(win, "Export cameras", 20, 60, 250, 40, true);
    6.89 -
    6.90 -	MSG msg;
    6.91 -	while(GetMessage(&msg, win->win, 0, 0)) {
    6.92 -		TranslateMessage(&msg);
    6.93 -		DispatchMessage(&msg);
    6.94 -	}
    6.95 -
    6.96 -	DestroyWindow(win->win);
    6.97 -	delete bn_ok;
    6.98 -	delete bn_cancel;
    6.99 -	delete ck_lights;
   6.100 -	delete ck_cameras;
   6.101 -	delete win;
   6.102 -
   6.103 -	return 0;
   6.104 -}
   6.105 -
   6.106 -static void init()
   6.107 -{
   6.108 -	static bool done_init;
   6.109 -	if(done_init) {
   6.110 -		return;
   6.111 -	}
   6.112 -	done_init = true;
   6.113 -
   6.114 -	size_t sz = mbstowcs(0, GOATSCE_WCLASS, 0);
   6.115 -	wchar_t *cname = new wchar_t[sz + 1];
   6.116 -	mbstowcs(cname, GOATSCE_WCLASS, sz + 1);
   6.117 -
   6.118 -	WNDCLASS wc;
   6.119 -	memset(&wc, 0, sizeof wc);
   6.120 -	wc.lpszClassName = cname;
   6.121 -	wc.hInstance = hinst;
   6.122 -	wc.lpfnWndProc = handle_msg;
   6.123 -	wc.style = CS_HREDRAW | CS_VREDRAW;
   6.124 -	wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
   6.125 -	wc.hCursor = LoadCursor(0, IDC_ARROW);
   6.126 -
   6.127 -	RegisterClass(&wc);
   6.128 -}
   6.129 -
   6.130 -static MinWidget *createwin(MinWidget *parent, const char *cls, const char *name,
   6.131 -		unsigned int style, int x, int y, int xsz, int ysz)
   6.132 -{
   6.133 -	init();
   6.134 -
   6.135 -	MinWidget *w = new MinWidget;
   6.136 -
   6.137 -	size_t sz = mbstowcs(0, cls, 0);
   6.138 -	wchar_t *wcls = new wchar_t[sz + 1];
   6.139 -	mbstowcs(wcls, cls, sz + 1);
   6.140 -
   6.141 -	sz = mbstowcs(0, name, 0);
   6.142 -	wchar_t *wname = new wchar_t[sz + 1];
   6.143 -	mbstowcs(wname, name, sz + 1);
   6.144 -
   6.145 -	if(x <= 0) x = CW_USEDEFAULT;
   6.146 -	if(y <= 0) y = CW_USEDEFAULT;
   6.147 -
   6.148 -	w->win = CreateWindow(wcls, wname, style, x, y, xsz, ysz, parent ? parent->win : 0, 0, hinst, 0);
   6.149 -
   6.150 -	delete [] wcls;
   6.151 -	delete [] wname;
   6.152 -
   6.153 -	if(!w->win) {
   6.154 -		delete w;
   6.155 -		return 0;
   6.156 -	}
   6.157 -	return w;
   6.158 -}
   6.159 -
   6.160 -
   6.161 -static LRESULT CALLBACK handle_msg(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam)
   6.162 -{
   6.163 -	switch(msg) {
   6.164 -	case WM_CLOSE:
   6.165 -		DestroyWindow(win);
   6.166 -		break;
   6.167 -
   6.168 -	default:
   6.169 -		return DefWindowProc(win, msg, wparam, lparam);
   6.170 -	}
   6.171 -
   6.172 -	return 0;
   6.173 -}
   6.174 \ No newline at end of file
     7.1 --- a/exporters/maxgoat/src/minwin.h	Tue Apr 01 13:11:04 2014 +0300
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,15 +0,0 @@
     7.4 -#ifndef MINWIN_H_
     7.5 -#define MINWIN_H_
     7.6 -
     7.7 -struct MinWidget;
     7.8 -typedef void (*MWCallback)(MinWidget*, void*);
     7.9 -
    7.10 -void mw_set_callback(MinWidget *w, MWCallback func, void *cls);
    7.11 -
    7.12 -MinWidget *mw_create_window(MinWidget *parent, const char *name, int x, int y, int xsz, int ysz);
    7.13 -MinWidget *mw_create_button(MinWidget *parent, const char *text, int x, int y, int xsz, int ysz);
    7.14 -MinWidget *mw_create_checkbox(MinWidget *parent, const char *text, int x, int y, int xsz, int ysz, bool checked);
    7.15 -
    7.16 -void mw_test();
    7.17 -
    7.18 -#endif	// MINWIN_H_
    7.19 \ No newline at end of file
     8.1 --- a/exporters/maxgoat_stub/maxgoat_stub.vcxproj	Tue Apr 01 13:11:04 2014 +0300
     8.2 +++ b/exporters/maxgoat_stub/maxgoat_stub.vcxproj	Sat Apr 19 07:56:43 2014 +0300
     8.3 @@ -33,7 +33,7 @@
     8.4    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     8.5      <ConfigurationType>DynamicLibrary</ConfigurationType>
     8.6      <UseDebugLibraries>true</UseDebugLibraries>
     8.7 -    <PlatformToolset>v100</PlatformToolset>
     8.8 +    <PlatformToolset>v110</PlatformToolset>
     8.9      <CharacterSet>Unicode</CharacterSet>
    8.10    </PropertyGroup>
    8.11    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    8.12 @@ -46,7 +46,7 @@
    8.13    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    8.14      <ConfigurationType>DynamicLibrary</ConfigurationType>
    8.15      <UseDebugLibraries>false</UseDebugLibraries>
    8.16 -    <PlatformToolset>v100</PlatformToolset>
    8.17 +    <PlatformToolset>v110</PlatformToolset>
    8.18      <WholeProgramOptimization>true</WholeProgramOptimization>
    8.19      <CharacterSet>Unicode</CharacterSet>
    8.20    </PropertyGroup>
    8.21 @@ -105,7 +105,7 @@
    8.22        <GenerateDebugInformation>true</GenerateDebugInformation>
    8.23      </Link>
    8.24      <PostBuildEvent>
    8.25 -      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2014)plugins\$(ProjectName).dle"</Command>
    8.26 +      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2015)plugins\$(ProjectName).dle"</Command>
    8.27      </PostBuildEvent>
    8.28    </ItemDefinitionGroup>
    8.29    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    8.30 @@ -143,7 +143,7 @@
    8.31        <OptimizeReferences>true</OptimizeReferences>
    8.32      </Link>
    8.33      <PostBuildEvent>
    8.34 -      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2014)plugins\$(ProjectName).dle"</Command>
    8.35 +      <Command>copy /Y "$(TargetPath)" "$(ADSK_3DSMAX_x64_2015)plugins\$(ProjectName).dle"</Command>
    8.36      </PostBuildEvent>
    8.37    </ItemDefinitionGroup>
    8.38    <ItemGroup>
     9.1 --- a/exporters/maxgoat_stub/src/stub.cc	Tue Apr 01 13:11:04 2014 +0300
     9.2 +++ b/exporters/maxgoat_stub/src/stub.cc	Sat Apr 19 07:56:43 2014 +0300
     9.3 @@ -143,7 +143,14 @@
     9.4  		goto done;
     9.5  	}
     9.6  
     9.7 -	result = ex->DoExport(name, eiface, iface);
     9.8 +	__try {
     9.9 +		result = ex->DoExport(name, eiface, iface);
    9.10 +	}
    9.11 +	__except(EXCEPTION_EXECUTE_HANDLER) {
    9.12 +		fprintf(logfile, "Exception caught!\n");
    9.13 +		delete ex;
    9.14 +		goto done;
    9.15 +	}
    9.16  	delete ex;
    9.17  
    9.18  	if((shutdown = (PluginShutdownFunc)GetProcAddress(dll, "LibShutdown"))) {
    10.1 --- a/goat3d.vcxproj	Tue Apr 01 13:11:04 2014 +0300
    10.2 +++ b/goat3d.vcxproj	Sat Apr 19 07:56:43 2014 +0300
    10.3 @@ -85,8 +85,8 @@
    10.4    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    10.5      <ConfigurationType>StaticLibrary</ConfigurationType>
    10.6      <UseDebugLibraries>true</UseDebugLibraries>
    10.7 -    <PlatformToolset>v100</PlatformToolset>
    10.8      <CharacterSet>Unicode</CharacterSet>
    10.9 +    <PlatformToolset>v110</PlatformToolset>
   10.10    </PropertyGroup>
   10.11    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   10.12      <ConfigurationType>StaticLibrary</ConfigurationType>
   10.13 @@ -98,9 +98,9 @@
   10.14    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
   10.15      <ConfigurationType>StaticLibrary</ConfigurationType>
   10.16      <UseDebugLibraries>false</UseDebugLibraries>
   10.17 -    <PlatformToolset>v100</PlatformToolset>
   10.18      <WholeProgramOptimization>true</WholeProgramOptimization>
   10.19      <CharacterSet>Unicode</CharacterSet>
   10.20 +    <PlatformToolset>v110</PlatformToolset>
   10.21    </PropertyGroup>
   10.22    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   10.23    <ImportGroup Label="ExtensionSettings">
    11.1 --- a/src/goat3d.cc	Tue Apr 01 13:11:04 2014 +0300
    11.2 +++ b/src/goat3d.cc	Sat Apr 19 07:56:43 2014 +0300
    11.3 @@ -780,7 +780,7 @@
    11.4  
    11.5  GOAT3DAPI void goat3d_add_node_child(struct goat3d_node *node, struct goat3d_node *child)
    11.6  {
    11.7 -	node->add_child(node);
    11.8 +	node->add_child(child);
    11.9  }
   11.10  
   11.11  GOAT3DAPI int goat3d_get_node_child_count(const struct goat3d_node *node)
    12.1 --- a/src/scene.cc	Tue Apr 01 13:11:04 2014 +0300
    12.2 +++ b/src/scene.cc	Sat Apr 19 07:56:43 2014 +0300
    12.3 @@ -38,7 +38,7 @@
    12.4  	cameras.clear();
    12.5  
    12.6  	for(size_t i=0; i<nodes.size(); i++) {
    12.7 -		delete_node_tree(nodes[i]);
    12.8 +		delete nodes[i];
    12.9  	}
   12.10  	nodes.clear();
   12.11  
    13.1 --- a/src/xform_node.cc	Tue Apr 01 13:11:04 2014 +0300
    13.2 +++ b/src/xform_node.cc	Sat Apr 19 07:56:43 2014 +0300
    13.3 @@ -75,6 +75,8 @@
    13.4  
    13.5  void XFormNode::add_child(XFormNode *child)
    13.6  {
    13.7 +	if(!child || child == this) return;
    13.8 +
    13.9  	children.push_back(child);
   13.10  	anm_link_node(anm, child->anm);
   13.11  	child->parent = this;