mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 23:51:41 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
135
Code/Tools/ASF_IMP/ASF_IMP.dsp
Normal file
135
Code/Tools/ASF_IMP/ASF_IMP.dsp
Normal file
@@ -0,0 +1,135 @@
|
||||
# Microsoft Developer Studio Project File - Name="asf_imp" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=asf_imp - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ASF_IMP.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ASF_IMP.mak" CFG="asf_imp - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "asf_imp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "asf_imp - Win32 Hybrid" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Commando/Code/Tools/ASF_IMP", SGHAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "asf_imp - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Z7 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib core.lib geom.lib maxutil.lib /nologo /subsystem:windows /dll /machine:I386 /out:"Release/asf_imp.dli"
|
||||
# SUBTRACT LINK32 /nodefaultlib
|
||||
|
||||
!ELSEIF "$(CFG)" == "asf_imp - Win32 Hybrid"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Hybrid"
|
||||
# PROP BASE Intermediate_Dir "Hybrid"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Hybrid"
|
||||
# PROP Intermediate_Dir "Hybrid"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /Z7 /O2 /I "c:\3dsmax2\maxsdk\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Z7 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib core.lib geom.lib util.lib /nologo /subsystem:windows /dll /machine:I386 /out:"Hybrid/asf_imp.dli"
|
||||
# SUBTRACT BASE LINK32 /nodefaultlib
|
||||
# ADD LINK32 odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib core.lib geom.lib maxutil.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"Hybrid\asf_imp.dli"
|
||||
# SUBTRACT LINK32 /nodefaultlib
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "asf_imp - Win32 Release"
|
||||
# Name "asf_imp - Win32 Hybrid"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ASF_import.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ASF_import.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Read_ASF.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asf_data.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\exception.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\read_asf.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ASF_import.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
280
Code/Tools/ASF_IMP/ASF_import.cpp
Normal file
280
Code/Tools/ASF_IMP/ASF_import.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// asf_import.cpp
|
||||
//
|
||||
// Acclaim Skeleton File import module
|
||||
//
|
||||
// James McNeill
|
||||
//
|
||||
// Created October 1996
|
||||
//
|
||||
// Copyright (c) 1996 Westwood Studios
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <Max.h>
|
||||
#include <istdplug.h>
|
||||
#include <splshape.h>
|
||||
#include <dummy.h>
|
||||
|
||||
#include "asf_resource.h"
|
||||
#include "asf_data.h"
|
||||
#include "read_asf.h"
|
||||
#include "exception.h"
|
||||
|
||||
static HINSTANCE hInstance;
|
||||
|
||||
static TCHAR * GetString ( int id )
|
||||
{
|
||||
static TCHAR buf[256];
|
||||
if (hInstance)
|
||||
return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int MessageBox ( int s1, int s2, int option = MB_OK )
|
||||
{
|
||||
TSTR str1(GetString(s1));
|
||||
TSTR str2(GetString(s2));
|
||||
return MessageBox(GetActiveWindow(), str1, str2, option);
|
||||
}
|
||||
|
||||
static int Alert ( int s1, int s2 = IDS_LIB_SHORT_DESC, int option = MB_OK )
|
||||
{
|
||||
return MessageBox(s1, s2, option);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Import
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class ASF_Import : public SceneImport
|
||||
{
|
||||
public:
|
||||
|
||||
ASF_Import();
|
||||
~ASF_Import();
|
||||
|
||||
int ExtCount(); // Number of extensions supported
|
||||
const TCHAR * Ext(int n); // Extension #n
|
||||
const TCHAR * LongDesc(); // Long ASCII description
|
||||
const TCHAR * ShortDesc(); // Short ASCII description
|
||||
const TCHAR * AuthorName(); // ASCII Author name
|
||||
const TCHAR * CopyrightMessage(); // ASCII Copyright message
|
||||
const TCHAR * OtherMessage1(); // Other message #1
|
||||
const TCHAR * OtherMessage2(); // Other message #2
|
||||
unsigned int Version(); // Version number * 100
|
||||
void ShowAbout(HWND); // Show DLL's "About..." box
|
||||
|
||||
int DoImport
|
||||
(
|
||||
const TCHAR * name,
|
||||
ImpInterface * i,
|
||||
Interface * gi,
|
||||
BOOL suppressPrompts=FALSE
|
||||
);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DllMain
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static int controlsInit = FALSE;
|
||||
|
||||
BOOL WINAPI DllMain
|
||||
(
|
||||
HINSTANCE hinstDLL,
|
||||
ULONG fdwReason,
|
||||
LPVOID lpvReserved
|
||||
)
|
||||
{
|
||||
hInstance = hinstDLL;
|
||||
|
||||
if ( !controlsInit )
|
||||
{
|
||||
controlsInit = TRUE;
|
||||
InitCustomControls(hInstance);
|
||||
InitCommonControls();
|
||||
}
|
||||
switch(fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH: break;
|
||||
case DLL_THREAD_ATTACH: break;
|
||||
case DLL_THREAD_DETACH: break;
|
||||
case DLL_PROCESS_DETACH: break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_ClassDesc
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class ASF_ClassDesc : public ClassDesc
|
||||
{
|
||||
public:
|
||||
int IsPublic() { return 1; }
|
||||
void * Create(BOOL loading = FALSE) { return new ASF_Import; }
|
||||
const TCHAR * ClassName() { return GetString(IDS_SHORT_DESC); }
|
||||
SClass_ID SuperClassID() { return SCENE_IMPORT_CLASS_ID; }
|
||||
Class_ID ClassID() { return Class_ID(0x74975aa6, 0x1810323f); }
|
||||
const TCHAR* Category() { return GetString(IDS_CATEGORY); }
|
||||
};
|
||||
|
||||
static ASF_ClassDesc ASF_desc;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// This is the interface to Jaguar:
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
__declspec( dllexport ) const TCHAR * LibDescription()
|
||||
{
|
||||
return GetString(IDS_LIB_LONG_DESC);
|
||||
}
|
||||
|
||||
__declspec( dllexport ) int LibNumberClasses()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
__declspec( dllexport ) ClassDesc * LibClassDesc(int i)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0: return & ASF_desc; break;
|
||||
default: return 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return version so can detect obsolete DLLs
|
||||
__declspec( dllexport ) ULONG LibVersion()
|
||||
{
|
||||
return VERSION_3DSMAX;
|
||||
}
|
||||
|
||||
//
|
||||
// ASF import module functions follow:
|
||||
//
|
||||
|
||||
ASF_Import::ASF_Import() {}
|
||||
ASF_Import::~ASF_Import() {}
|
||||
|
||||
int ASF_Import::ExtCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Extensions supported for import/export modules
|
||||
|
||||
const TCHAR * ASF_Import::Ext(int n)
|
||||
{
|
||||
if ( n == 0 ) return _T("ASF");
|
||||
else return _T("");
|
||||
}
|
||||
|
||||
const TCHAR * ASF_Import::LongDesc()
|
||||
{
|
||||
return GetString(IDS_LONG_DESC);
|
||||
}
|
||||
|
||||
const TCHAR * ASF_Import::ShortDesc()
|
||||
{
|
||||
return GetString(IDS_SHORT_DESC);
|
||||
}
|
||||
|
||||
const TCHAR * ASF_Import::AuthorName()
|
||||
{
|
||||
return GetString(IDS_AUTHOR_NAME);
|
||||
}
|
||||
|
||||
const TCHAR * ASF_Import::CopyrightMessage()
|
||||
{
|
||||
return GetString(IDS_COPYRIGHT);
|
||||
}
|
||||
|
||||
const TCHAR * ASF_Import::OtherMessage1()
|
||||
{
|
||||
return _T("");
|
||||
}
|
||||
|
||||
const TCHAR * ASF_Import::OtherMessage2()
|
||||
{
|
||||
return _T("");
|
||||
}
|
||||
|
||||
unsigned int ASF_Import::Version()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
void ASF_Import::ShowAbout(HWND hWnd)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// asf_load
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static int asf_load
|
||||
(
|
||||
const TCHAR * filename,
|
||||
ImpInterface * iface,
|
||||
Interface * gi
|
||||
)
|
||||
{
|
||||
// Load the skeleton definition file.
|
||||
|
||||
try
|
||||
{
|
||||
Skeleton_Class skeleton ( filename, iface, gi );
|
||||
}
|
||||
catch ( const Parse_Error & error )
|
||||
{
|
||||
MessageBox ( GetActiveWindow (), error.message (), "Parse error",
|
||||
MB_OK );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create a matching skeleton in 3DS Max.
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Import::DoImport
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
int ASF_Import::DoImport
|
||||
(
|
||||
const TCHAR * filename,
|
||||
ImpInterface * iface,
|
||||
Interface * gi,
|
||||
BOOL
|
||||
)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = asf_load ( filename, iface, gi );
|
||||
if(status == 0)
|
||||
status = IMPEXP_CANCEL;
|
||||
|
||||
return (status <= 0) ? IMPEXP_FAIL : status;
|
||||
}
|
||||
8
Code/Tools/ASF_IMP/ASF_import.def
Normal file
8
Code/Tools/ASF_IMP/ASF_import.def
Normal file
@@ -0,0 +1,8 @@
|
||||
LIBRARY asf_imp
|
||||
EXPORTS
|
||||
LibDescription @1
|
||||
LibNumberClasses @2
|
||||
LibClassDesc @3
|
||||
LibVersion @4
|
||||
SECTIONS
|
||||
.data READ WRITE
|
||||
147
Code/Tools/ASF_IMP/ASF_import.rc
Normal file
147
Code/Tools/ASF_IMP/ASF_import.rc
Normal file
@@ -0,0 +1,147 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "asf_resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_IMPORTOPTIONS DIALOG DISCARDABLE 0, 0, 123, 266
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Import DXF File"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,67,231,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,67,247,50,14
|
||||
GROUPBOX "Derive Objects From:",IDC_STATIC,6,4,112,50
|
||||
CONTROL "&Layer",IDC_OBJ_LAYER,"Button",BS_AUTORADIOBUTTON |
|
||||
WS_TABSTOP,44,17,29,10
|
||||
CONTROL "&Color",IDC_OBJ_COLOR,"Button",BS_AUTORADIOBUTTON,44,28,
|
||||
28,10
|
||||
CONTROL "&Entity",IDC_OBJ_ENTITY,"Button",BS_AUTORADIOBUTTON,44,
|
||||
38,30,10
|
||||
GROUPBOX "Weld Vertices:",IDC_STATIC,6,57,112,41
|
||||
RTEXT "Weld Threshold:",IDC_STATIC,13,72,55,8
|
||||
CONTROL "",IDC_WELDENTRY,"CustEdit",WS_TABSTOP,69,71,36,10
|
||||
CONTROL "",IDC_WELDSPINNER,"SpinnerControl",0x0,106,71,7,10
|
||||
CONTROL "&Weld",IDC_WELD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
47,83,30,10
|
||||
GROUPBOX "Auto-Smooth:",IDC_STATIC,6,102,112,40
|
||||
RTEXT "Smooth Angle:",IDC_STATIC,16,117,48,8
|
||||
CONTROL "",IDC_SMOOTHENTRY,"CustEdit",WS_TABSTOP,65,117,36,10
|
||||
CONTROL "",IDC_SMOOTHSPINNER,"SpinnerControl",0x0,102,117,7,10
|
||||
CONTROL "&Auto-Smooth",IDC_AUTOSMOOTH,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,34,128,53,10
|
||||
GROUPBOX "Arc Degrees:",IDC_STATIC,6,146,112,30
|
||||
RTEXT "&Degrees:",IDC_STATIC,23,161,31,8
|
||||
CONTROL "00",IDC_ARCENTRY,"CustEdit",WS_TABSTOP,56,160,36,10
|
||||
CONTROL "",IDC_ARCSPINNER,"SpinnerControl",0x0,93,160,7,10
|
||||
GROUPBOX "Miscellaneous:",IDC_STATIC,6,180,112,46
|
||||
CONTROL "&Remove Double Faces",IDC_REMOVEDOUBLES,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,19,193,85,10
|
||||
CONTROL "&Fill Polylines",IDC_FILLPOLYLINES,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,19,203,52,10
|
||||
CONTROL "&Unify Normals",IDC_UNIFYNORMALS,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,19,213,56,10
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"asf_resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_LIB_SHORT_DESC "ASF Import"
|
||||
IDS_LIB_LONG_DESC "Acclaim Skeleton Format Import DLL"
|
||||
IDS_IMPORTING_ASF "Importing ASF"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_ERR_OPENING_FILE "Error opening file"
|
||||
IDS_TH_OUTOFMEMORY "Out of memory"
|
||||
IDS_SHORT_DESC "ASF File"
|
||||
IDS_LONG_DESC "Acclaim Skeleton Format File"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_CATEGORY "Scene Import"
|
||||
IDS_AUTHOR_NAME "James McNeill"
|
||||
IDS_COPYRIGHT "Copyright 1996 Westwood Studios"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
IDS_BAD_HEADER "Bad header in CME file."
|
||||
IDS_UNEXPECTED_EOF "Unexpected end of file in CME file."
|
||||
IDS_NODE_CREATION_ERROR "Node creation error."
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
62
Code/Tools/ASF_IMP/Asf_resource.h
Normal file
62
Code/Tools/ASF_IMP/Asf_resource.h
Normal file
@@ -0,0 +1,62 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by ASF_import.rc
|
||||
//
|
||||
#define IDD_IMPORTOPTIONS 101
|
||||
#define IDC_OBJ_LAYER 1000
|
||||
#define IDC_OBJ_COLOR 1001
|
||||
#define IDC_OBJ_ENTITY 1002
|
||||
#define IDC_REMOVEDOUBLES 1004
|
||||
#define IDC_FILLPOLYLINES 1005
|
||||
#define IDC_AUTOSMOOTH 1006
|
||||
#define IDC_WELDENTRY 1007
|
||||
#define IDC_WELDSPINNER 1008
|
||||
#define IDC_SMOOTHSPINNER 1009
|
||||
#define IDC_SMOOTHENTRY 1010
|
||||
#define IDC_ARCSPINNER 1011
|
||||
#define IDC_ARCENTRY 1012
|
||||
#define IDC_WELD 1013
|
||||
#define IDC_UNIFYNORMALS 1014
|
||||
#define IDC_DBG1 1015
|
||||
#define IDS_TH_SCENEIMPORT 40217
|
||||
#define IDS_CATEGORY 40217
|
||||
#define IDS_TH_TOM_HUDSON 40222
|
||||
#define IDS_AUTHOR_NAME 40222
|
||||
#define IDS_TH_COPYRIGHT_YOST_GROUP 40223
|
||||
#define IDS_COPYRIGHT 40223
|
||||
#define IDS_TH_ERR_OPENING_FILE 40225
|
||||
#define IDS_ERR_OPENING_FILE 40225
|
||||
#define IDS_TH_OUTOFMEMORY 40230
|
||||
#define IDS_TH_AUTOCAD 40236
|
||||
#define IDS_SHORT_DESC 40236
|
||||
#define IDS_TH_AUTOCADDXFFILE 40238
|
||||
#define IDS_LONG_DESC 40238
|
||||
#define IDS_TH_DXFIMP 40240
|
||||
#define IDS_LIB_SHORT_DESC 40240
|
||||
#define IDS_TH_DXFIMPORTDLL 40241
|
||||
#define IDS_LIB_LONG_DESC 40241
|
||||
#define IDS_TH_PARTIALREAD 40242
|
||||
#define IDS_TH_UNKNOWNERR 40243
|
||||
#define IDS_TH_FINALIZING 40244
|
||||
#define IDS_TH_IMPORTINGDXF 40245
|
||||
#define IDS_IMPORTING_CME 40245
|
||||
#define IDS_IMPORTING_ASF 40245
|
||||
#define IDS_TH_INVALIDRATSNEST 40253
|
||||
#define IDS_TH_INVALIDSPLINEMESH 40254
|
||||
#define IDS_TH_INVALID3DMESH 40255
|
||||
#define IDS_TH_ERRORINDXF 40256
|
||||
#define IDS_BAD_HEADER 40257
|
||||
#define IDS_UNEXPECTED_EOF 40258
|
||||
#define IDS_NODE_CREATION_ERROR 40259
|
||||
#define IDC_STATIC -1
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1016
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
818
Code/Tools/ASF_IMP/Read_ASF.cpp
Normal file
818
Code/Tools/ASF_IMP/Read_ASF.cpp
Normal file
@@ -0,0 +1,818 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Max.h>
|
||||
#include <istdplug.h>
|
||||
|
||||
#include "asf_data.h"
|
||||
#include "read_asf.h"
|
||||
#include "exception.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Lexer::ASF_Lexer
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
ASF_Lexer::ASF_Lexer
|
||||
(
|
||||
const char * file_name
|
||||
):
|
||||
Input_file ( file_name, "r" )
|
||||
{
|
||||
Current_char = tolower ( fgetc ( Input_file.fp ) );
|
||||
advance ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Lexer::skip_whitespace
|
||||
//----------------------------------------------------------------------------
|
||||
// Skip whitespace and comments, leaving the Current_char pointing to the
|
||||
// first non-whitespace character in the input stream.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void ASF_Lexer::skip_whitespace ()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if ( Current_char == '#' ) // Strip out comments
|
||||
{
|
||||
while ( Current_char != '\n' && Current_char != EOF )
|
||||
Current_char = tolower ( fgetc ( Input_file.fp ) );
|
||||
}
|
||||
else if ( (isspace ( Current_char ) && Current_char != '\n') ||
|
||||
Current_char == ',' ||
|
||||
Current_char == '(' ||
|
||||
Current_char == ')' )
|
||||
{
|
||||
Current_char = tolower ( fgetc ( Input_file.fp ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Lexer::advance
|
||||
//----------------------------------------------------------------------------
|
||||
// Advance to the next token in the input stream.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void ASF_Lexer::advance ()
|
||||
{
|
||||
skip_whitespace ();
|
||||
|
||||
if ( Current_char == EOF )
|
||||
{
|
||||
Current_type = EOF_MARKER;
|
||||
strcpy ( Current_text, "<end of file>" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Current_char == '\n' )
|
||||
{
|
||||
Current_type = NEWLINE;
|
||||
strcpy ( Current_text, "<newline>" );
|
||||
Current_char = tolower ( fgetc ( Input_file.fp ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Current_type = TOKEN;
|
||||
|
||||
// Read characters into the token text buffer.
|
||||
|
||||
int i = 0;
|
||||
|
||||
while ( ! isspace (Current_char) &&
|
||||
Current_char != '#' &&
|
||||
Current_char != ',' &&
|
||||
Current_char != '(' &&
|
||||
Current_char != ')' &&
|
||||
Current_char != EOF )
|
||||
{
|
||||
if ( i >= (MAX_TOKEN_LENGTH - 1) )
|
||||
{
|
||||
// Abort -- maximum token length exceeded.
|
||||
|
||||
throw Parse_Error ( "Maximum token length exceeded." );
|
||||
}
|
||||
|
||||
Current_text [i] = Current_char;
|
||||
++ i;
|
||||
|
||||
Current_char = tolower ( fgetc ( Input_file.fp ) );
|
||||
}
|
||||
|
||||
Current_text [i] = '\0';
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::Skeleton_Class
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Skeleton_Class::Skeleton_Class
|
||||
(
|
||||
const char * file_name,
|
||||
ImpInterface * iface,
|
||||
Interface * gi
|
||||
) :
|
||||
Angle_multiplier (DEGREES_TO_RADIANS),
|
||||
Length_multiplier (1.0f),
|
||||
First_bone (NULL),
|
||||
Import_interface (iface),
|
||||
Max_interface (gi)
|
||||
{
|
||||
ASF_Lexer lexer ( file_name );
|
||||
|
||||
parse_units_block ( lexer );
|
||||
parse_root_block ( lexer );
|
||||
parse_bonedata_block ( lexer );
|
||||
parse_hierarchy_block ( lexer );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::~Skeleton_Class
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Skeleton_Class::~Skeleton_Class ()
|
||||
{
|
||||
Bone_Class * p = First_bone;
|
||||
|
||||
while ( p != NULL )
|
||||
{
|
||||
Bone_Class * delete_p = p;
|
||||
p = p->next_bone ();
|
||||
|
||||
delete delete_p;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::parse_units_block
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::parse_units_block ( ASF_Lexer & lexer )
|
||||
{
|
||||
skip_unrecognized_blocks ( lexer );
|
||||
|
||||
match_token ( lexer, ":units" );
|
||||
match_newline ( lexer );
|
||||
|
||||
BOOL mass_defined = FALSE;
|
||||
BOOL length_defined = FALSE;
|
||||
BOOL angle_defined = FALSE;
|
||||
|
||||
while (1)
|
||||
{
|
||||
verify_token ( lexer );
|
||||
|
||||
if ( strcmp ( lexer.text (), "mass" ) == 0 )
|
||||
{
|
||||
if ( mass_defined )
|
||||
throw Parse_Error ( "Multiple mass definitions." );
|
||||
|
||||
lexer.advance ();
|
||||
skip_token ( lexer ); // Ignore the mass definition.
|
||||
match_newline ( lexer );
|
||||
|
||||
mass_defined = TRUE;
|
||||
}
|
||||
else if ( strcmp ( lexer.text (), "length" ) == 0 )
|
||||
{
|
||||
if ( length_defined )
|
||||
throw Parse_Error ( "Multiple length definitions." );
|
||||
|
||||
lexer.advance ();
|
||||
verify_token ( lexer );
|
||||
Length_multiplier = 1.0f / float_token ( lexer );
|
||||
match_newline ( lexer );
|
||||
|
||||
length_defined = TRUE;
|
||||
}
|
||||
else if ( strcmp ( lexer.text (), "angle" ) == 0 )
|
||||
{
|
||||
if ( angle_defined )
|
||||
throw Parse_Error ( "Multiple angle definitions." );
|
||||
|
||||
lexer.advance ();
|
||||
verify_token ( lexer );
|
||||
if ( strcmp ( lexer.text (), "deg" ) == 0 )
|
||||
Angle_multiplier = DEGREES_TO_RADIANS;
|
||||
else if ( strcmp ( lexer.text (), "rad" ) == 0 )
|
||||
Angle_multiplier = 1.0f;
|
||||
else
|
||||
throw Parse_Error
|
||||
( "\"deg\" or \"rad\" expected after angle keyword." );
|
||||
|
||||
lexer.advance ();
|
||||
match_newline ( lexer );
|
||||
|
||||
angle_defined = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::parse_root_block
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::parse_root_block ( ASF_Lexer & lexer )
|
||||
{
|
||||
skip_unrecognized_blocks ( lexer );
|
||||
|
||||
match_token ( lexer, ":root" );
|
||||
match_newline ( lexer );
|
||||
|
||||
// Create a root bone.
|
||||
|
||||
Bone_Class * new_bone = new Bone_Class;
|
||||
new_bone->set_name ( "root" );
|
||||
|
||||
// The rotation order for orientation offset.
|
||||
|
||||
match_token ( lexer, "axis" );
|
||||
skip_token ( lexer ); // &&& get rotation order for orientation offset.
|
||||
match_newline ( lexer );
|
||||
|
||||
// The order of transformations for root.
|
||||
|
||||
match_token ( lexer, "order" );
|
||||
for ( int i = 0; i < 6; ++ i )
|
||||
{
|
||||
verify_token ( lexer );
|
||||
|
||||
if ( strcmp ( lexer.text (), "rx" ) == 0 )
|
||||
new_bone->add_axis ( ROTATE_X );
|
||||
else if ( strcmp ( lexer.text (), "ry" ) == 0 )
|
||||
new_bone->add_axis ( ROTATE_Y );
|
||||
else if ( strcmp ( lexer.text (), "rz" ) == 0 )
|
||||
new_bone->add_axis ( ROTATE_Z );
|
||||
else if ( strcmp ( lexer.text (), "tx" ) == 0 )
|
||||
new_bone->add_axis ( TRANSLATE_X );
|
||||
else if ( strcmp ( lexer.text (), "ty" ) == 0 )
|
||||
new_bone->add_axis ( TRANSLATE_Y );
|
||||
else if ( strcmp ( lexer.text (), "tz" ) == 0 )
|
||||
new_bone->add_axis ( TRANSLATE_Z );
|
||||
else
|
||||
throw Parse_Error ( "Unrecognized order token in :root." );
|
||||
|
||||
lexer.advance ();
|
||||
}
|
||||
match_newline ( lexer );
|
||||
|
||||
// Translation data for root node.
|
||||
|
||||
match_token ( lexer, "position" );
|
||||
skip_token ( lexer ); // &&&
|
||||
skip_token ( lexer ); // &&&
|
||||
skip_token ( lexer ); // &&&
|
||||
match_newline ( lexer );
|
||||
|
||||
// Rotation data to orient the skeleton.
|
||||
|
||||
match_token ( lexer, "orientation" );
|
||||
float rot0 = float_token ( lexer ) * Angle_multiplier;
|
||||
float rot1 = float_token ( lexer ) * Angle_multiplier;
|
||||
float rot2 = float_token ( lexer ) * Angle_multiplier;
|
||||
match_newline ( lexer );
|
||||
|
||||
Matrix3 axis_tm;
|
||||
axis_tm.IdentityMatrix ();
|
||||
axis_tm.RotateX ( rot0 );
|
||||
axis_tm.RotateY ( rot1 );
|
||||
axis_tm.RotateZ ( rot2 );
|
||||
new_bone->set_axis_tm ( axis_tm );
|
||||
|
||||
new_bone->set_direction ( Point3 (0,0,0) );
|
||||
new_bone->set_length ( 0.0f );
|
||||
|
||||
add_bone_to_list ( new_bone );
|
||||
new_bone->create_node ( Import_interface, Max_interface );
|
||||
|
||||
// Add an AppData chunk to the root node to indicate how much to scale
|
||||
// its position keys.
|
||||
Position_Key_Scale_Chunk * data_p = (Position_Key_Scale_Chunk *)
|
||||
malloc ( sizeof (Position_Key_Scale_Chunk) );
|
||||
|
||||
data_p->Position_Key_Scale = Length_multiplier;
|
||||
|
||||
new_bone->add_app_data ( 2, data_p, sizeof (Position_Key_Scale_Chunk) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::parse_bonedata_block
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::parse_bonedata_block ( ASF_Lexer & lexer )
|
||||
{
|
||||
skip_unrecognized_blocks ( lexer );
|
||||
|
||||
match_token ( lexer, ":bonedata" );
|
||||
match_newline ( lexer );
|
||||
|
||||
// Parse bone definition blocks.
|
||||
|
||||
while (1)
|
||||
{
|
||||
verify_token ( lexer );
|
||||
if ( strcmp ( lexer.text (), "begin" ) == 0 )
|
||||
{
|
||||
parse_bone ( lexer );
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::parse_hierarchy_block
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::parse_hierarchy_block ( ASF_Lexer & lexer )
|
||||
{
|
||||
skip_unrecognized_blocks ( lexer );
|
||||
|
||||
match_token ( lexer, ":hierarchy" );
|
||||
match_newline ( lexer );
|
||||
|
||||
match_token ( lexer, "begin" );
|
||||
match_newline ( lexer );
|
||||
|
||||
while (1)
|
||||
{
|
||||
verify_token ( lexer );
|
||||
if ( strcmp ( lexer.text (), "end" ) == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_hierarchy_line ( lexer );
|
||||
}
|
||||
}
|
||||
|
||||
lexer.advance ();
|
||||
match_newline ( lexer );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::parse_hierarchy_line
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::parse_hierarchy_line ( ASF_Lexer & lexer )
|
||||
{
|
||||
verify_token ( lexer );
|
||||
Bone_Class * parent_bone = find_bone ( lexer.text () );
|
||||
if ( parent_bone == NULL )
|
||||
throw Parse_Error ( "Undefined parent bone." );
|
||||
lexer.advance ();
|
||||
|
||||
while ( lexer.type () == TOKEN )
|
||||
{
|
||||
Bone_Class * child_bone = find_bone ( lexer.text () );
|
||||
if ( child_bone == NULL )
|
||||
throw Parse_Error ( "Undefined child bone." );
|
||||
|
||||
child_bone->set_parent ( parent_bone );
|
||||
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
match_newline ( lexer );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::find_bone
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Bone_Class * Skeleton_Class::find_bone ( const char * name )
|
||||
{
|
||||
Bone_Class * p = First_bone;
|
||||
|
||||
while ( p != NULL )
|
||||
{
|
||||
if ( strcmp ( name, p->name () ) == 0 )
|
||||
break;
|
||||
|
||||
p = p->next_bone ();
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// lh_to_rh
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static Point3 lh_to_rh ( Point3 point )
|
||||
{
|
||||
Point3 new_point;
|
||||
|
||||
new_point.x = point.x;
|
||||
new_point.y = -point.z;
|
||||
new_point.z = point.y;
|
||||
|
||||
return new_point;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::parse_bone
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::parse_bone ( ASF_Lexer & lexer )
|
||||
{
|
||||
match_token ( lexer, "begin" );
|
||||
match_newline ( lexer );
|
||||
|
||||
// Create a new bone object.
|
||||
|
||||
Bone_Class * new_bone = new Bone_Class;
|
||||
|
||||
// Optional ID number.
|
||||
|
||||
verify_token ( lexer );
|
||||
if ( strcmp ( lexer.text (), "id" ) == 0 )
|
||||
{
|
||||
lexer.advance ();
|
||||
skip_token ( lexer ); // Ignore the bone ID number for now.
|
||||
match_newline ( lexer );
|
||||
}
|
||||
|
||||
// Name.
|
||||
|
||||
match_token ( lexer, "name" );
|
||||
verify_token ( lexer );
|
||||
new_bone->set_name ( lexer.text () );
|
||||
lexer.advance ();
|
||||
match_newline ( lexer );
|
||||
|
||||
// Direction vector.
|
||||
|
||||
match_token ( lexer, "direction" );
|
||||
Point3 direction;
|
||||
direction.x = float_token ( lexer );
|
||||
direction.y = float_token ( lexer );
|
||||
direction.z = float_token ( lexer );
|
||||
new_bone->set_direction ( direction );
|
||||
match_newline ( lexer );
|
||||
|
||||
// Length.
|
||||
|
||||
match_token ( lexer, "length" );
|
||||
new_bone->set_length ( float_token ( lexer ) * Length_multiplier / (float)GetMasterScale(UNITS_INCHES));
|
||||
match_newline ( lexer );
|
||||
|
||||
// Rotation axis in world coordinates, with order of rotations.
|
||||
|
||||
match_token ( lexer, "axis" );
|
||||
float rot0 = float_token ( lexer ) * Angle_multiplier;
|
||||
float rot1 = float_token ( lexer ) * Angle_multiplier;
|
||||
float rot2 = float_token ( lexer ) * Angle_multiplier;
|
||||
|
||||
// &&& Ultimately this should handle any order of rotations.
|
||||
match_token ( lexer, "xyz" );
|
||||
|
||||
match_newline ( lexer );
|
||||
|
||||
Matrix3 axis_tm;
|
||||
axis_tm.IdentityMatrix ();
|
||||
axis_tm.RotateX ( rot0 );
|
||||
axis_tm.RotateY ( rot1 );
|
||||
axis_tm.RotateZ ( rot2 );
|
||||
new_bone->set_axis_tm ( axis_tm );
|
||||
|
||||
// Optional mass of skinbody associated with this bone.
|
||||
|
||||
verify_token ( lexer );
|
||||
if ( strcmp ( lexer.text (), "bodymass" ) == 0 )
|
||||
{
|
||||
lexer.advance ();
|
||||
skip_token ( lexer ); // Ignore the bodymass.
|
||||
match_newline ( lexer );
|
||||
}
|
||||
|
||||
// Optional position of center of mass along the bone.
|
||||
|
||||
verify_token ( lexer );
|
||||
if ( strcmp ( lexer.text (), "cofmass" ) == 0 )
|
||||
{
|
||||
lexer.advance ();
|
||||
skip_token ( lexer ); // Ignore the center of mass position.
|
||||
match_newline ( lexer );
|
||||
}
|
||||
|
||||
// Optional degrees of freedom.
|
||||
|
||||
verify_token ( lexer );
|
||||
if ( strcmp ( lexer.text (), "dof" ) == 0 )
|
||||
{
|
||||
lexer.advance ();
|
||||
|
||||
if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "rx" ) == 0 )
|
||||
{
|
||||
new_bone->add_axis ( ROTATE_X );
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "ry" ) == 0 )
|
||||
{
|
||||
new_bone->add_axis ( ROTATE_Y );
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "rz" ) == 0 )
|
||||
{
|
||||
new_bone->add_axis ( ROTATE_Z );
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "l" ) == 0 )
|
||||
{
|
||||
new_bone->add_axis ( TRANSLATE_LENGTH );
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
match_newline ( lexer );
|
||||
|
||||
// Limits for the given degrees of freedom.
|
||||
|
||||
match_token ( lexer, "limits" );
|
||||
|
||||
// &&&
|
||||
|
||||
while ( strcmp ( lexer.text (), "end" ) != 0 )
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
match_token ( lexer, "end" );
|
||||
match_newline ( lexer );
|
||||
|
||||
// Add the bone to the list of bones.
|
||||
|
||||
add_bone_to_list ( new_bone );
|
||||
|
||||
new_bone->create_node ( Import_interface, Max_interface );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::skip_unrecognized_blocks
|
||||
//----------------------------------------------------------------------------
|
||||
// It is assumed that the current lexeme is the first on a line.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::skip_unrecognized_blocks
|
||||
(
|
||||
ASF_Lexer & lexer
|
||||
)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if ( lexer.type () == EOF_MARKER )
|
||||
break;
|
||||
if ( strcmp ( lexer.text (), ":units" ) == 0 )
|
||||
break;
|
||||
if ( strcmp ( lexer.text (), ":root" ) == 0 )
|
||||
break;
|
||||
if ( strcmp ( lexer.text (), ":bonedata" ) == 0 )
|
||||
break;
|
||||
if ( strcmp ( lexer.text (), ":hierarchy" ) == 0 )
|
||||
break;
|
||||
|
||||
skip_to_next_line ( lexer );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::skip_to_next_line
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::skip_to_next_line
|
||||
(
|
||||
ASF_Lexer & lexer
|
||||
)
|
||||
{
|
||||
while ( lexer.type () != NEWLINE &&
|
||||
lexer.type () != EOF_MARKER )
|
||||
lexer.advance ();
|
||||
|
||||
if ( lexer.type () == NEWLINE )
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::match_newline
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::match_newline
|
||||
(
|
||||
ASF_Lexer & lexer
|
||||
)
|
||||
{
|
||||
char message_buffer [ 512 ];
|
||||
|
||||
if ( lexer.type () != NEWLINE )
|
||||
{
|
||||
sprintf ( message_buffer, "Expected newline; found \"%s\" instead.",
|
||||
lexer.text () );
|
||||
throw Parse_Error ( message_buffer );
|
||||
}
|
||||
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::verify_token
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::verify_token
|
||||
(
|
||||
ASF_Lexer & lexer
|
||||
)
|
||||
{
|
||||
char message_buffer [ 512 ];
|
||||
|
||||
if ( lexer.type () != TOKEN )
|
||||
{
|
||||
sprintf ( message_buffer, "Expected token; found \"%s\" instead.",
|
||||
lexer.text () );
|
||||
throw Parse_Error ( message_buffer );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::skip_token
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::skip_token
|
||||
(
|
||||
ASF_Lexer & lexer
|
||||
)
|
||||
{
|
||||
verify_token ( lexer );
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::float_token
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
float Skeleton_Class::float_token
|
||||
(
|
||||
ASF_Lexer & lexer
|
||||
)
|
||||
{
|
||||
verify_token ( lexer );
|
||||
float value = (float) strtod ( lexer.text (), NULL );
|
||||
lexer.advance ();
|
||||
return value;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::match_token
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::match_token
|
||||
(
|
||||
ASF_Lexer & lexer,
|
||||
const char * token_text
|
||||
)
|
||||
{
|
||||
char message_buffer [ 512 ];
|
||||
|
||||
verify_token ( lexer );
|
||||
|
||||
if ( strcmp ( lexer.text (), token_text ) != 0 )
|
||||
{
|
||||
sprintf ( message_buffer, "Expected \"%s\"; found \"%s\" instead.",
|
||||
token_text, lexer.text () );
|
||||
throw Parse_Error ( message_buffer );
|
||||
}
|
||||
|
||||
lexer.advance ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class::add_bone_to_list
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Skeleton_Class::add_bone_to_list
|
||||
(
|
||||
Bone_Class * new_bone
|
||||
)
|
||||
{
|
||||
new_bone->set_next_bone ( First_bone );
|
||||
First_bone = new_bone;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Bone_Class::create_node
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Bone_Class::create_node
|
||||
(
|
||||
ImpInterface * import_interface,
|
||||
Interface * max_interface
|
||||
)
|
||||
{
|
||||
Node = import_interface->CreateNode ();
|
||||
Node->SetName ( Name );
|
||||
|
||||
// Create a box object.
|
||||
|
||||
GeomObject * obj = (GeomObject *) max_interface->CreateInstance
|
||||
( GEOMOBJECT_CLASS_ID, Class_ID (BOXOBJ_CLASS_ID, 0) );
|
||||
|
||||
IParamArray *iBoxParams = obj->GetParamBlock();
|
||||
assert(iBoxParams);
|
||||
|
||||
// Set the value of width, height and length.
|
||||
|
||||
int width_index = obj->GetParamBlockIndex(BOXOBJ_WIDTH);
|
||||
assert(width_index >= 0);
|
||||
iBoxParams->SetValue(width_index,TimeValue(0),Length / 4);
|
||||
|
||||
int height_index = obj->GetParamBlockIndex(BOXOBJ_HEIGHT);
|
||||
assert(height_index >= 0);
|
||||
iBoxParams->SetValue(height_index,TimeValue(0),Length);
|
||||
|
||||
int length_index = obj->GetParamBlockIndex(BOXOBJ_LENGTH);
|
||||
assert(length_index >= 0);
|
||||
iBoxParams->SetValue(length_index,TimeValue(0),Length / 4);
|
||||
|
||||
Node->Reference ( (Object *) obj );
|
||||
|
||||
Node->GetINode ()->SetNodeTM ( 0, Axis_tm );
|
||||
|
||||
// Add the node to the scene.
|
||||
|
||||
import_interface->AddNodeToScene ( Node );
|
||||
|
||||
// Add an AppData chunk to the inode to indicate which transformation
|
||||
// axes are active.
|
||||
|
||||
ASF_Data_Chunk * data_p = (ASF_Data_Chunk *)
|
||||
malloc ( sizeof (ASF_Data_Chunk) );
|
||||
|
||||
*data_p = Active_axes;
|
||||
|
||||
add_app_data ( 1, data_p, sizeof (ASF_Data_Chunk) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Bone_Class::set_parent
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Bone_Class::set_parent ( Bone_Class * parent_bone )
|
||||
{
|
||||
Parent_bone = parent_bone;
|
||||
parent_bone->Node->GetINode ()->AttachChild ( Node->GetINode () );
|
||||
|
||||
// Build the child node's transform matrix.
|
||||
|
||||
Matrix3 parent_tm = Node->GetINode ()->GetParentTM ( 0 );
|
||||
|
||||
Matrix3 child_tm = Axis_tm;
|
||||
child_tm.Translate ( Normalize (parent_bone->Direction) *
|
||||
parent_bone->Length );
|
||||
child_tm.Translate ( parent_tm.GetTrans () );
|
||||
|
||||
Node->GetINode ()->SetNodeTM ( 0, child_tm );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Bone_Class::add_app_data
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Bone_Class::add_app_data ( int chunk_id, void * data, int data_size )
|
||||
{
|
||||
Node->GetINode ()->AddAppDataChunk
|
||||
(
|
||||
Class_ID(0x74975aa6, 0x1810323f),
|
||||
SCENE_IMPORT_CLASS_ID,
|
||||
chunk_id,
|
||||
data_size,
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
61
Code/Tools/ASF_IMP/asf_data.h
Normal file
61
Code/Tools/ASF_IMP/asf_data.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Axes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
enum Axis_Names
|
||||
{
|
||||
ROTATE_X,
|
||||
ROTATE_Y,
|
||||
ROTATE_Z,
|
||||
TRANSLATE_X,
|
||||
TRANSLATE_Y,
|
||||
TRANSLATE_Z,
|
||||
TRANSLATE_LENGTH
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Data_Chunk
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
struct ASF_Data_Chunk
|
||||
{
|
||||
ASF_Data_Chunk () : Number_of_axes (0) {}
|
||||
void add_axis ( Axis_Names new_axis )
|
||||
{
|
||||
if ( Number_of_axes < 7 )
|
||||
{
|
||||
Axis [Number_of_axes] = new_axis;
|
||||
++ Number_of_axes;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Number_of_axes;
|
||||
Axis_Names Axis [ 7 ];
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Position_Key_Scale_Chunk
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
struct Position_Key_Scale_Chunk
|
||||
{
|
||||
float Position_Key_Scale;
|
||||
};
|
||||
45
Code/Tools/ASF_IMP/exception.h
Normal file
45
Code/Tools/ASF_IMP/exception.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class Exception
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char * message () const
|
||||
{
|
||||
return "General exception.";
|
||||
}
|
||||
};
|
||||
|
||||
class Parse_Error : public Exception
|
||||
{
|
||||
public:
|
||||
|
||||
Parse_Error ( const char * message ) :
|
||||
Message (message)
|
||||
{}
|
||||
|
||||
virtual const char * message () const
|
||||
{
|
||||
return Message;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
const char * Message;
|
||||
};
|
||||
194
Code/Tools/ASF_IMP/read_asf.h
Normal file
194
Code/Tools/ASF_IMP/read_asf.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// File_Class
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class File_Class
|
||||
{
|
||||
public:
|
||||
|
||||
FILE * fp;
|
||||
|
||||
File_Class ( const char * filename, const char * mode )
|
||||
{
|
||||
fp = fopen ( filename, mode );
|
||||
}
|
||||
|
||||
~File_Class ()
|
||||
{
|
||||
if ( fp != NULL )
|
||||
fclose ( fp );
|
||||
fp = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Lexeme_Type
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
enum ASF_Lexeme_Type
|
||||
{
|
||||
EOF_MARKER,
|
||||
TOKEN,
|
||||
NEWLINE
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ASF_Lexer
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define MAX_TOKEN_LENGTH 512
|
||||
|
||||
class ASF_Lexer
|
||||
{
|
||||
public:
|
||||
|
||||
ASF_Lexer ( const char * file_name );
|
||||
|
||||
ASF_Lexeme_Type type () const { return Current_type; }
|
||||
const char * text () const { return Current_text; }
|
||||
|
||||
void advance ();
|
||||
|
||||
protected:
|
||||
|
||||
void skip_whitespace ();
|
||||
|
||||
File_Class Input_file;
|
||||
int Current_char;
|
||||
|
||||
ASF_Lexeme_Type Current_type;
|
||||
char Current_text [ MAX_TOKEN_LENGTH ];
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Bone_Class
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class Bone_Class
|
||||
{
|
||||
public:
|
||||
|
||||
Bone_Class ():
|
||||
Name (""),
|
||||
Direction (Point3 (0,0,0)),
|
||||
Parent_bone (NULL),
|
||||
Next_bone (NULL),
|
||||
Length (0.0f)
|
||||
{
|
||||
Axis_tm.IdentityMatrix ();
|
||||
}
|
||||
|
||||
~Bone_Class () { delete [] Name; }
|
||||
|
||||
void set_name ( const char * name )
|
||||
{
|
||||
Name = new char [ strlen (name) + 1 ];
|
||||
strcpy ( Name, name );
|
||||
}
|
||||
|
||||
void set_next_bone ( Bone_Class * next_bone )
|
||||
{
|
||||
Next_bone = next_bone;
|
||||
}
|
||||
|
||||
void set_length ( float length ) { Length = length; }
|
||||
void set_direction ( Point3 direction ) { Direction = direction; }
|
||||
void set_axis_tm ( const Matrix3 & axis_tm ) { Axis_tm = axis_tm; }
|
||||
|
||||
void add_axis ( Axis_Names axis ) { Active_axes.add_axis ( axis ); }
|
||||
|
||||
void set_parent ( Bone_Class * parent_bone );
|
||||
|
||||
const char * name () const { return Name; }
|
||||
Bone_Class * next_bone () const { return Next_bone; }
|
||||
|
||||
void create_node
|
||||
(
|
||||
ImpInterface * import_interface,
|
||||
Interface * max_interface
|
||||
);
|
||||
|
||||
void add_app_data ( int chunk_id, void * data, int data_size );
|
||||
|
||||
private:
|
||||
|
||||
char * Name;
|
||||
|
||||
Point3 Direction;
|
||||
Matrix3 Axis_tm;
|
||||
|
||||
Bone_Class * Parent_bone;
|
||||
Bone_Class * Next_bone;
|
||||
|
||||
ImpNode * Node;
|
||||
|
||||
float Length;
|
||||
|
||||
ASF_Data_Chunk Active_axes;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Skeleton_Class
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define DEGREES_TO_RADIANS 1.7453293e-2f
|
||||
|
||||
class Skeleton_Class
|
||||
{
|
||||
public:
|
||||
|
||||
Skeleton_Class
|
||||
(
|
||||
const char * file_name,
|
||||
ImpInterface *,
|
||||
Interface *
|
||||
);
|
||||
|
||||
~Skeleton_Class ();
|
||||
|
||||
protected:
|
||||
|
||||
void add_bone_to_list ( Bone_Class * new_bone );
|
||||
|
||||
Bone_Class * find_bone ( const char * name );
|
||||
|
||||
void parse_units_block ( ASF_Lexer & );
|
||||
void parse_root_block ( ASF_Lexer & );
|
||||
void parse_bonedata_block ( ASF_Lexer & );
|
||||
void parse_hierarchy_block ( ASF_Lexer & );
|
||||
void parse_hierarchy_line ( ASF_Lexer & );
|
||||
void parse_bone ( ASF_Lexer & );
|
||||
void skip_unrecognized_blocks ( ASF_Lexer & );
|
||||
void skip_to_next_line ( ASF_Lexer & );
|
||||
void match_newline ( ASF_Lexer & );
|
||||
void match_token ( ASF_Lexer &, const char * );
|
||||
void skip_token ( ASF_Lexer & );
|
||||
void verify_token ( ASF_Lexer & );
|
||||
float float_token ( ASF_Lexer & );
|
||||
|
||||
float Angle_multiplier; // Converts angle to radians.
|
||||
float Length_multiplier;
|
||||
|
||||
ImpInterface * Import_interface;
|
||||
Interface * Max_interface;
|
||||
|
||||
Bone_Class * First_bone;
|
||||
};
|
||||
Reference in New Issue
Block a user