/* ** 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 . */ //---------------------------------------------------------------------------- // 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; };