├── plugins ├── sourcetools │ ├── res │ │ ├── description │ │ │ ├── fcamioloader.h │ │ │ ├── fcamioloader.res │ │ │ ├── fsmdloader.h │ │ │ ├── fqcloader.h │ │ │ ├── fsmdloader.res │ │ │ └── fqcloader.res │ │ ├── strings_en-US │ │ │ ├── description │ │ │ │ ├── fcamioloader.str │ │ │ │ ├── fsmdloader.str │ │ │ │ └── fqcloader.str │ │ │ └── c4d_strings.str │ │ └── c4d_symbols.h │ ├── .gitignore │ ├── source │ │ ├── qc │ │ │ ├── qcparser.h │ │ │ ├── modelproperties.h │ │ │ ├── qcloader.h │ │ │ ├── qcformat.h │ │ │ ├── qcparser.cpp │ │ │ └── qcloader.cpp │ │ ├── smd │ │ │ ├── smdparser.h │ │ │ ├── smdformat.h │ │ │ ├── smdloader.h │ │ │ ├── smdparser.cpp │ │ │ └── smdloader.cpp │ │ ├── vmt │ │ │ ├── vmtparser.h │ │ │ ├── vmtformat.h │ │ │ ├── vmtloader.h │ │ │ ├── vmtloader.cpp │ │ │ └── vmtparser.cpp │ │ ├── camio │ │ │ ├── camioparser.h │ │ │ ├── camioformat.h │ │ │ ├── camioloader.h │ │ │ ├── camioloader.cpp │ │ │ └── camioparser.cpp │ │ ├── utility.h │ │ ├── vtf │ │ │ ├── vtfloader.h │ │ │ ├── vtfformat.h │ │ │ └── vtfloader.cpp │ │ ├── error.h │ │ ├── benchmark.h │ │ ├── utility.cpp │ │ ├── error.cpp │ │ ├── benchmark.cpp │ │ ├── main.cpp │ │ └── sharedgrammar.h │ └── project │ │ └── projectdefinition.txt └── project │ ├── .gitignore │ └── projectdefinition.txt ├── .gitignore ├── .github └── FUNDING.yml ├── .gitmodules ├── LICENSE └── how_to_build.txt /plugins/sourcetools/res/description/fcamioloader.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/sourcetools/res/description/fcamioloader.res: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/sourcetools/res/strings_en-US/description/fcamioloader.str: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | generated 3 | frameworks 4 | *.manifest 5 | *.vscode -------------------------------------------------------------------------------- /plugins/project/.gitignore: -------------------------------------------------------------------------------- 1 | _obj 2 | *.vs 3 | *.sln 4 | plugins.xcodeproj -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: xNWP 4 | -------------------------------------------------------------------------------- /plugins/sourcetools/.gitignore: -------------------------------------------------------------------------------- 1 | *.pdb 2 | *.ilk 3 | *.user 4 | *.xdl64 5 | *.filters 6 | *.vcxproj 7 | *.props -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "plugins/sourcetools/dependencies/PEGTL"] 2 | path = plugins/sourcetools/dependencies/PEGTL 3 | url = https://github.com/taocpp/PEGTL 4 | -------------------------------------------------------------------------------- /plugins/sourcetools/source/qc/qcparser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_file.h" 4 | #include "maxon/integer.h" 5 | #include "qcformat.h" 6 | 7 | namespace st::qc 8 | { 9 | maxon::Bool ParseQC(const Filename& file, QuakeCFormat& qc); 10 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/smd/smdparser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_file.h" 4 | #include "maxon/integer.h" 5 | #include "smdformat.h" 6 | 7 | namespace st::smd 8 | { 9 | maxon::Bool ParseSMD(const Filename& file, StudiomdlData& smd); 10 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/vmt/vmtparser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_file.h" 4 | #include "maxon/integer.h" 5 | #include "vmtformat.h" 6 | 7 | namespace st::vmt 8 | { 9 | maxon::Bool ParseVMT(const Filename& file, ValveMaterialType& vmt); 10 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/camio/camioparser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_file.h" 4 | #include "maxon/integer.h" 5 | #include "camioformat.h" 6 | 7 | namespace st::camio 8 | { 9 | maxon::Bool ParseCamIO(const Filename& filename, CamIO& camio); 10 | 11 | maxon::Bool CheckCamIOFileHeader(const Filename& filename); 12 | } -------------------------------------------------------------------------------- /plugins/project/projectdefinition.txt: -------------------------------------------------------------------------------- 1 | Platform=Win64;OSX 2 | Type=Solution 3 | Solution=\ 4 | plugins/sourcetools; 5 | 6 | // include natvis files in Visual Studio solution file 7 | AdditionalSolutionFiles=\ 8 | ..\..\frameworks\core.framework\project\typeviewer\msvc\maxon.natvis;\ 9 | ..\..\frameworks\cinema.framework\project\typeviewer\msvc\c4dapi.natvis -------------------------------------------------------------------------------- /plugins/sourcetools/res/c4d_symbols.h: -------------------------------------------------------------------------------- 1 | #ifndef SOURCETOOLS_C4D_SYMBOLS_H__ 2 | #define SOURCETOOLS_C4D_SYMBOLS_H__ 3 | 4 | enum 5 | { 6 | _FIRST_ELEMENT_ = 10000, 7 | S_BUILDINGFILE, 8 | S_PARSINGFILE, 9 | S_BUILDINGFILE_SUB, 10 | S_PARSINGFILE_SUB, 11 | S_INVALID_MATERIAL_PATH, 12 | S_PARSE_ERROR, 13 | S_CAMIO_BAD_VERSION 14 | }; 15 | 16 | #endif // !SOURCETOOLS_C4D_SYMBOLS_H__ -------------------------------------------------------------------------------- /plugins/sourcetools/res/description/fsmdloader.h: -------------------------------------------------------------------------------- 1 | #ifndef FSMDLOADER_H__ 2 | #define FSMDLOADER_H__ 3 | 4 | enum 5 | { 6 | SMD_LOADER_SCALE = 1100, 7 | SMD_LOADER_ROTATE, 8 | SMD_LOADER_IMPORT_UNDER_NULL, 9 | SMD_LOADER_IMPORT_ANIMATION, 10 | SMD_LOADER_IMPORT_MESH, 11 | SMD_LOADER_IMPORT_WEIGHTS, 12 | SMD_LOADER_IMPORT_SKELETON 13 | }; 14 | 15 | #endif // !FSMDLOADER_H__ -------------------------------------------------------------------------------- /plugins/sourcetools/source/utility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_file.h" 4 | #include "c4d_tools.h" 5 | #include 6 | 7 | namespace st 8 | { 9 | bool ResolveLocalFilepath(Filename& fp, const std::vector& searchdirectories, const Bool& isdir = false); 10 | 11 | const maxon::Matrix SrcToC4DTransformMatrix = MatrixScale(Vector(-1.0f, 1.0f, 1.0f)) * MatrixRotX(PI / 2); 12 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/vtf/vtfloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_filterdata.h" 4 | 5 | #define ID_VTFLOADER 1053587 6 | 7 | namespace st::vtf 8 | { 9 | class LoaderData : public BitmapLoaderData 10 | { 11 | public: 12 | Bool Identify(const Filename& name, UChar* probe, Int32 size) override; 13 | IMAGERESULT Load(const Filename& name, BaseBitmap* bm, Int32 frame) override; 14 | 15 | static Bool RegisterPlugin(); 16 | }; 17 | } -------------------------------------------------------------------------------- /plugins/sourcetools/res/strings_en-US/c4d_strings.str: -------------------------------------------------------------------------------- 1 | STRINGTABLE 2 | { 3 | S_BUILDINGFILE "Building #"; 4 | S_PARSINGFILE "Parsing #"; 5 | S_BUILDINGFILE_SUB "# - Building #"; 6 | S_PARSINGFILE_SUB "# - Parsing #"; 7 | S_INVALID_MATERIAL_PATH "Root material path must be a valid directory."; 8 | S_PARSE_ERROR "Error parsing file #"; 9 | S_CAMIO_BAD_VERSION "CamIO version # not supported. Max supported version is #."; 10 | } -------------------------------------------------------------------------------- /plugins/sourcetools/project/projectdefinition.txt: -------------------------------------------------------------------------------- 1 | // plugin for win and macOS 2 | Platform=Win64 3 | Type=DLL 4 | 5 | // uses the "classic" API and the new core 6 | APIS=cinema.framework;core.framework 7 | 8 | // turns on additional legacy support 9 | C4D=true 10 | 11 | // to turn off stylechecks on can set the level to 0 or just set "stylecheck" to false 12 | stylecheck.level=0 13 | 14 | // custom module id 15 | ModuleId=com.thatnwp.Cinema4DSourceTools 16 | 17 | Exclude=/dependencies/ 18 | 19 | AdditionalIncludeDirectories=../dependencies/PEGTL/include -------------------------------------------------------------------------------- /plugins/sourcetools/source/vmt/vmtformat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace st::vmt 7 | { 8 | namespace Types 9 | { 10 | enum class ShaderType 11 | { 12 | UNKNOWN, 13 | LIGHTMAPPEDGENERIC, 14 | CHARACTER 15 | }; 16 | 17 | enum class ParameterType 18 | { 19 | BASETEXTURE, 20 | BUMPMAP, 21 | SSBUMP, 22 | TRANSLUCENT 23 | }; 24 | } 25 | 26 | struct ValveMaterialType 27 | { 28 | Types::ShaderType Shader; 29 | std::unordered_map Parameters; 30 | }; 31 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/error.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "maxon/string.h" 4 | 5 | namespace st 6 | { 7 | void iLog(const maxon::String& msg); 8 | void iLogError(const maxon::String& msg, const char* FILE, const char* FUNC, unsigned int LINE); 9 | void iLogErrorWhat(const maxon::String& WHAT, const char* FILE, const char* FUNC, unsigned int LINE); 10 | } 11 | 12 | #define Log( MSG ) st::iLog(maxon::String(MSG)) 13 | #define LogError( MSG ) st::iLogError(maxon::String(MSG), __FILE__, __func__, __LINE__) 14 | #define LogErrorWhat( WHAT ) st::iLogErrorWhat(maxon::String(WHAT.what()), __FILE__, __func__, __LINE__) -------------------------------------------------------------------------------- /plugins/sourcetools/res/strings_en-US/description/fsmdloader.str: -------------------------------------------------------------------------------- 1 | STRINGTABLE Fsmdloader 2 | { 3 | Fsmdloader "Source Studiomdl Data (SMD)"; 4 | 5 | S_GENERAL "General"; 6 | SMD_LOADER_IMPORT_UNDER_NULL "Import as child of a Null"; 7 | S_SCALEORIENTATION "Scale/Orientation"; 8 | SMD_LOADER_SCALE "Scale"; 9 | SMD_LOADER_ROTATE "Rotate"; 10 | SMD_LOADER_IMPORT_MESH "Mesh"; 11 | SMD_LOADER_IMPORT_ANIMATION "Animation"; 12 | S_IMPORT_OPTIONS "Import"; 13 | SMD_LOADER_IMPORT_WEIGHTS "Weights"; 14 | SMD_LOADER_IMPORT_SKELETON "Skeleton"; 15 | } -------------------------------------------------------------------------------- /plugins/sourcetools/res/description/fqcloader.h: -------------------------------------------------------------------------------- 1 | #ifndef FQCLOADER_H__ 2 | #define FQCLOADER_H__ 3 | 4 | enum 5 | { 6 | QC_LOADER_IMPORT_UNDER_NULL = 1200, 7 | QC_LOADER_SCALE, 8 | QC_LOADER_ROTATE, 9 | QC_LOADER_IMPORT_SKELETON, 10 | QC_LOADER_IMPORT_ANIMATION, 11 | QC_LOADER_IMPORT_MESH, 12 | QC_LOADER_IMPORT_WEIGHTS, 13 | QC_LOADER_MATERIAL_PATH, 14 | SOURCETYPE_NONE, 15 | SOURCETYPE_VMF_VTF, 16 | SOURCETYPE_VMF_TGA, 17 | SOURCETYPE_VMF_OTHER, 18 | QC_LOADER_SOURCETYPE, 19 | QC_MATERIAL_EXTENSION, 20 | QC_LOADER_IMPORT_IK, 21 | QC_LOADER_IMPORT_PHYSICS 22 | }; 23 | 24 | #endif // !FQCLOADER_H__ -------------------------------------------------------------------------------- /plugins/sourcetools/source/camio/camioformat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace st::camio 8 | { 9 | namespace Types 10 | { 11 | struct Frame 12 | { 13 | maxon::Float32 time, 14 | xPosition, yPosition, zPosition, 15 | xRotation, yRotation, zRotation, 16 | fov; 17 | 18 | Frame(Float32 Time) : time(Time) { } 19 | }; 20 | 21 | enum class SCALETYPE 22 | { 23 | UNKNOWN = 0, 24 | NONE = 1, 25 | ALIENSWARM = 2 26 | }; 27 | } 28 | 29 | struct CamIO 30 | { 31 | maxon::Int32 Version; 32 | Types::SCALETYPE Scaling; 33 | std::vector Frames; 34 | }; 35 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/qc/modelproperties.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace st::qc::ModelProperties 6 | { 7 | enum class PropertyTypes 8 | { 9 | NONE, 10 | EyeBall 11 | }; 12 | 13 | class ModelProperty 14 | { 15 | public: 16 | ModelProperty() = default; 17 | virtual ~ModelProperty() = default; 18 | 19 | virtual PropertyTypes GetType() = 0; 20 | }; 21 | 22 | struct ModelPropertyEyeball : public ModelProperty 23 | { 24 | ModelPropertyEyeball(String name) 25 | : Name(name), EyeballCenter(), YawOffset(0.0f) { } 26 | 27 | PropertyTypes GetType() override { return PropertyTypes::EyeBall; } 28 | 29 | String Name; 30 | String ParentBoneName; 31 | Vector EyeballCenter; 32 | String MaterialName; 33 | Float YawOffset; 34 | }; 35 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/vmt/vmtloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "vmtformat.h" 4 | 5 | #include "c4d_filterdata.h" 6 | 7 | #define ID_VMTLOADER 1056375 8 | 9 | namespace st::vmt 10 | { 11 | class LoaderData : public SceneLoaderData 12 | { 13 | static NodeData* Create(); 14 | 15 | public: 16 | struct Settings 17 | { 18 | std::vector cdmaterials; 19 | maxon::String BitmapExtension = "vtf"_s; 20 | }; 21 | 22 | Bool Identify(BaseSceneLoader* node, const Filename& name, UChar* probe, Int32 size) override; 23 | FILEERROR Load(BaseSceneLoader* node, const Filename& name, BaseDocument* doc, SCENEFILTER filterflags, maxon::String* error, BaseThread* bt) override; 24 | 25 | static Material* CreateVMT(const ValveMaterialType& vmt, const Settings& config); 26 | 27 | static Bool RegisterPlugin(); 28 | }; 29 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/benchmark.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_string.h" 4 | #include 5 | 6 | #ifdef ST_PROFILING 7 | #define IF_PROFILING(CODE) CODE 8 | #else 9 | #define IF_PROFILING(CODE) 10 | #endif 11 | 12 | namespace st 13 | { 14 | class Benchmark 15 | { 16 | std::chrono::time_point _start; 17 | Float64 _elapsedTime; 18 | String _name; 19 | Bool _stopped; 20 | Bool _printOnDestruct; 21 | 22 | Benchmark() = default; 23 | 24 | public: 25 | Benchmark(const String& name, Bool printOnDestruct = true, Bool startImmediately = true); 26 | ~Benchmark(); 27 | 28 | void StopBenchmark(); 29 | void StartBenchmark(); 30 | Float64 GetElapsedSeconds() const; 31 | String GetElapsedTimeFormatted() const; 32 | Bool IsRunning() const; 33 | void PrintOnDestruct(Bool val); 34 | }; 35 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/qc/qcloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "qcformat.h" 5 | 6 | #define ID_QCLOADER 1055516 7 | 8 | namespace st::qc 9 | { 10 | class LoaderData : public SceneLoaderData 11 | { 12 | static NodeData* Create(); 13 | 14 | public: 15 | Bool Identify(BaseSceneLoader* node, const Filename& name, UChar* probe, Int32 size) override; 16 | FILEERROR Load(BaseSceneLoader* node, const Filename& name, BaseDocument* doc, SCENEFILTER filterflags, maxon::String* error, BaseThread* bt) override; 17 | Bool Init(GeListNode* node) override; 18 | Bool GetDEnabling(GeListNode* node, const DescID& id, const GeData& data, DESCFLAGS_ENABLE flags, const BaseContainer* itemdesc) override; 19 | Bool GetDParameter(GeListNode* node, const DescID& id, GeData& t_data, DESCFLAGS_GET& flags) override; 20 | 21 | static Bool RegisterPlugin(); 22 | }; 23 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/camio/camioloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define ID_CAMIOLOADER 1000001 // TODO: Test ID, replace with registered ID for release!!! 6 | 7 | namespace st::camio 8 | { 9 | class LoaderData : public SceneLoaderData 10 | { 11 | static NodeData* Create(); 12 | 13 | public: 14 | Bool Identify(BaseSceneLoader* node, const Filename& name, UChar* probe, Int32 size) override; 15 | FILEERROR Load(BaseSceneLoader* node, const Filename& name, BaseDocument* doc, SCENEFILTER filterflags, maxon::String* error, BaseThread* bt) override; 16 | //Bool Init(GeListNode* node) override; 17 | //Bool GetDEnabling(GeListNode* node, const DescID& id, const GeData& data, DESCFLAGS_ENABLE flags, const BaseContainer* itemdesc) override; 18 | //Bool GetDParameter(GeListNode* node, const DescID& id, GeData& t_data, DESCFLAGS_GET& flags) override; 19 | 20 | static Bool RegisterPlugin(); 21 | }; 22 | } -------------------------------------------------------------------------------- /plugins/sourcetools/res/description/fsmdloader.res: -------------------------------------------------------------------------------- 1 | CONTAINER Fsmdloader 2 | { 3 | NAME Fsmdloader; 4 | 5 | GROUP 6 | { 7 | GROUP 8 | { 9 | NAME S_GENERAL; 10 | DEFAULT 1; 11 | 12 | BOOL SMD_LOADER_IMPORT_UNDER_NULL {} 13 | } 14 | 15 | GROUP 16 | { 17 | NAME S_SCALEORIENTATION; 18 | DEFAULT 1; 19 | 20 | REAL SMD_LOADER_SCALE 21 | { 22 | MIN 0.01; 23 | MAX 100; 24 | STEP 0.1; 25 | } 26 | 27 | VECTOR SMD_LOADER_ROTATE { UNIT DEGREE; } 28 | } 29 | 30 | GROUP 31 | { 32 | NAME S_IMPORT_OPTIONS; 33 | DEFAULT 1; 34 | 35 | BOOL SMD_LOADER_IMPORT_SKELETON {} 36 | BOOL SMD_LOADER_IMPORT_ANIMATION {} 37 | BOOL SMD_LOADER_IMPORT_MESH {} 38 | BOOL SMD_LOADER_IMPORT_WEIGHTS {} 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /plugins/sourcetools/res/strings_en-US/description/fqcloader.str: -------------------------------------------------------------------------------- 1 | STRINGTABLE Fqcloader 2 | { 3 | Fqcloader "Source QuakeC (QC)"; 4 | 5 | S_GENERAL "General"; 6 | QC_LOADER_IMPORT_UNDER_NULL "Import as child of a Null"; 7 | S_SCALEORIENTATION "Scale/Orientation"; 8 | QC_LOADER_SCALE "Scale"; 9 | QC_LOADER_ROTATE "Rotate"; 10 | S_IMPORT_OPTIONS "Import"; 11 | 12 | QC_LOADER_IMPORT_SKELETON "Skeleton"; 13 | QC_LOADER_IMPORT_MESH "Mesh"; 14 | QC_LOADER_IMPORT_WEIGHTS "Weights"; 15 | S_MATERIALS "Materials"; 16 | QC_LOADER_MATERIAL_PATH "Root Material Directory"; 17 | QC_LOADER_SOURCETYPE "Material Source"; 18 | SOURCETYPE_NONE "None"; 19 | SOURCETYPE_VMF_VTF "VMF + VTF"; 20 | SOURCETYPE_VMF_TGA "VMF + TGA"; 21 | SOURCETYPE_VMF_OTHER "VMF + Other"; 22 | QC_MATERIAL_EXTENSION "Image File Extension"; 23 | QC_LOADER_IMPORT_ANIMATION "Animation"; 24 | QC_LOADER_IMPORT_IK "IK Tags"; 25 | QC_LOADER_IMPORT_PHYSICS "Physics/Collision Mesh"; 26 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Brett Anthony 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /plugins/sourcetools/source/qc/qcformat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "modelproperties.h" 7 | 8 | namespace st::qc 9 | { 10 | namespace Types 11 | { 12 | struct Mesh 13 | { 14 | Mesh() = default; 15 | Mesh(String name) : Name(name) {} 16 | String Name; 17 | String Filepath; 18 | }; 19 | 20 | struct Model : public Mesh 21 | { 22 | Model(String name) : Mesh(name) {} 23 | std::vector> Properties; 24 | }; 25 | 26 | struct BodyGroup 27 | { 28 | BodyGroup(String name) : Name(name), Blank(false) {} 29 | String Name; 30 | std::vector Meshes; 31 | bool Blank = false; 32 | }; 33 | 34 | struct IkRule 35 | { 36 | IkRule(String name) : Name(name) {} 37 | String Name; 38 | String EndBone; 39 | }; 40 | } 41 | 42 | struct QuakeCFormat 43 | { 44 | std::vector BodyMeshes; 45 | std::vector BodyGroups; 46 | std::vector Models; 47 | std::vector cdmaterials; 48 | std::vector IkRules; 49 | Types::Mesh PhysicsMesh; 50 | }; 51 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/utility.cpp: -------------------------------------------------------------------------------- 1 | #include "utility.h" 2 | 3 | #include "c4d.h" 4 | 5 | namespace st 6 | { 7 | bool ResolveLocalFilepath(Filename& fp, const std::vector& searchdirectories, const Bool& isdir) 8 | { 9 | Filename Match; 10 | maxon::String strFp = fp.GetString(); 11 | 12 | // direct match 13 | for (const auto& dir : searchdirectories) 14 | { 15 | maxon::String strMatch = dir.GetString(); 16 | if (!(strMatch.EndsWith('/') || strMatch.EndsWith('\\'))) 17 | { 18 | strMatch.AppendChar('/').GetValue(); 19 | } 20 | 21 | if (strFp.StartsWith('.')) 22 | { 23 | strFp.Erase(0, 1).GetValue(); 24 | } 25 | 26 | if (strFp.StartsWith('/') || strFp.StartsWith('\\')) 27 | { 28 | strFp.Erase(0, 1).GetValue(); 29 | } 30 | 31 | strMatch += strFp; 32 | strMatch.Replace('\\', '/').GetValue(); 33 | Match = strMatch; 34 | 35 | if (GeFExist(Match, isdir)) 36 | { 37 | fp = Match; 38 | return true; 39 | } 40 | } 41 | 42 | // soft match 43 | for (const auto& dir : searchdirectories) 44 | { 45 | if (GeSearchFile(dir, fp, &Match)) 46 | { 47 | fp = Match; 48 | return true; 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | } -------------------------------------------------------------------------------- /how_to_build.txt: -------------------------------------------------------------------------------- 1 | NOTE: This is an experimental build, some features may not work as intended, or at all. 2 | 3 | We currently build against Cinema 4D R21.107 4 | 5 | 1. Make sure you've cloned the repository with --recurse-submodules to include needed submodules. 6 | 7 | 2. Extract the frameworks folder from the sdk.zip file in your Cinema 4D directory (default is: C:\Program Files\Maxon Cinema 4D R) to the root of the C4DST directory. (Don't extract folders from frameworks, just have the entire frameworks folder in the root of C4DST.) 8 | 9 | 3. Download the project tool associated with your Cinema 4D version from the Maxon developer website: https://developers.maxon.net 10 | 11 | 4. Generate project files from a terminal with the following command: kernel_app_64bit.exe g_updateproject=\Cinema-4D-Source-Tools (path must be absolute, not relative) 12 | 13 | 5. Open the generated solution file located at: plugins\project\plugins.sln 14 | 15 | 5a. If you are asked to upgrade the project, don't. You may need to install additional Windows SDK's or Visual C++ build tools to compile the project. 16 | 17 | 6. Build the sourcetools project as per usual. 18 | 19 | == Debugging Setup (optional) == 20 | 21 | 7. Select your Cinema 4D executable as the debugging command. 22 | 23 | 8. Add the following command parameters to automate loading of the plugin: g_additionalModulePath=$(ProjectDir)..\.. 24 | 25 | == Profiling Setup (optional) == 26 | 9. Define the preprocessor macro 'ST_PROFILING' on the sourcetools project to have benchmarking data printed to the c4d console. -------------------------------------------------------------------------------- /plugins/sourcetools/source/smd/smdformat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace st::smd 8 | { 9 | namespace Types 10 | { 11 | struct Bone 12 | { 13 | Int16 Id; 14 | String Name; 15 | Int16 ParentId; 16 | }; 17 | 18 | struct Point3f 19 | { 20 | Float32 x, y, z; 21 | 22 | Float32 Distance(const Point3f& p) const { 23 | return maxon::Sqrt( 24 | maxon::Sqr(this->x - p.x) + 25 | maxon::Sqr(this->y - p.y) + 26 | maxon::Sqr(this->z - p.z)); 27 | } 28 | }; 29 | 30 | struct SkeletonAnimationEntry 31 | { 32 | UInt16 Id; 33 | Point3f Position; 34 | Point3f Rotation; 35 | }; 36 | 37 | struct SkeletonAnimationFrame 38 | { 39 | UInt32 Time; 40 | std::vector Entries; 41 | }; 42 | 43 | struct WeightmapEntry 44 | { 45 | Int16 BoneId; 46 | Float32 Weight; 47 | 48 | bool operator==(const WeightmapEntry& wm) const { 49 | return 50 | (this->BoneId == wm.BoneId) && 51 | (this->Weight == wm.Weight); 52 | } 53 | }; 54 | 55 | struct Vertex 56 | { 57 | UInt16 ParentBone; 58 | Point3f Position; 59 | Point3f Normals; 60 | Float32 u; 61 | Float32 v; 62 | std::vector WeightMapEntries; 63 | }; 64 | 65 | struct Triangle 66 | { 67 | String Material; 68 | Vertex Vertices[3]; 69 | }; 70 | } 71 | 72 | struct StudiomdlData 73 | { 74 | UChar Version; 75 | std::vector Bones; 76 | std::vector SkeletonAnimation; 77 | std::vector Triangles; 78 | }; 79 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/smd/smdloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "c4d_filterdata.h" 4 | #include "smdformat.h" 5 | 6 | #include 7 | 8 | #define ID_SMDLOADER 1054419 9 | 10 | namespace st::smd 11 | { 12 | class LoaderData : public SceneLoaderData 13 | { 14 | static NodeData* Create(); 15 | 16 | public: 17 | Bool Identify(BaseSceneLoader* node, const Filename& name, UChar* probe, Int32 size) override; 18 | FILEERROR Load(BaseSceneLoader* node, const Filename& name, BaseDocument* doc, SCENEFILTER filterflags, maxon::String* error, BaseThread* bt) override; 19 | Bool Init(GeListNode* node) override; 20 | Bool GetDEnabling(GeListNode* node, const DescID& id, const GeData& data, DESCFLAGS_ENABLE flags, const BaseContainer* itemdesc) override; 21 | Bool GetDParameter(GeListNode* node, const DescID& id, GeData& t_data, DESCFLAGS_GET& flags) override; 22 | 23 | struct BoneMapData 24 | { 25 | std::int16_t ParentId; 26 | BaseObject* Object; 27 | }; 28 | 29 | struct Settings 30 | { 31 | Float Scale = 1.0f; 32 | maxon::Vector Orientation; 33 | std::map Skeleton; 34 | maxon::Bool IncludeAnimation; 35 | maxon::Bool IncludeMesh; 36 | maxon::Bool IncludeWeights; 37 | maxon::Bool IncludeSkeleton; 38 | maxon::Bool IncludeUVW; 39 | maxon::Bool IncludePolySelections; 40 | maxon::Bool IncludeNormals; 41 | BaseDocument* doc; 42 | }; 43 | 44 | struct SMDObject 45 | { 46 | PolygonObject* Mesh = nullptr; 47 | std::map Skeleton; 48 | }; 49 | 50 | static SMDObject CreateSMD(const StudiomdlData& smd, const Settings& config); 51 | 52 | static Bool RegisterPlugin(); 53 | }; 54 | } -------------------------------------------------------------------------------- /plugins/sourcetools/res/description/fqcloader.res: -------------------------------------------------------------------------------- 1 | CONTAINER Fqcloader 2 | { 3 | NAME Fqcloader; 4 | 5 | GROUP 6 | { 7 | GROUP 8 | { 9 | NAME S_GENERAL; 10 | DEFAULT 1; 11 | 12 | BOOL QC_LOADER_IMPORT_UNDER_NULL {} 13 | } 14 | 15 | GROUP 16 | { 17 | NAME S_SCALEORIENTATION; 18 | DEFAULT 1; 19 | 20 | REAL QC_LOADER_SCALE 21 | { 22 | MIN 0.01; 23 | MAX 100; 24 | STEP 0.1; 25 | } 26 | 27 | VECTOR QC_LOADER_ROTATE { UNIT DEGREE; } 28 | } 29 | 30 | GROUP 31 | { 32 | NAME S_IMPORT_OPTIONS; 33 | DEFAULT 1; 34 | 35 | BOOL QC_LOADER_IMPORT_SKELETON {} 36 | BOOL QC_LOADER_IMPORT_ANIMATION {} 37 | BOOL QC_LOADER_IMPORT_MESH {} 38 | BOOL QC_LOADER_IMPORT_WEIGHTS {} 39 | BOOL QC_LOADER_IMPORT_IK {} 40 | BOOL QC_LOADER_IMPORT_PHYSICS {} 41 | } 42 | 43 | GROUP 44 | { 45 | NAME S_MATERIALS; 46 | DEFAULT 1; 47 | 48 | LONG QC_LOADER_SOURCETYPE 49 | { 50 | CYCLE 51 | { 52 | SOURCETYPE_NONE; 53 | -1; 54 | SOURCETYPE_VMF_VTF; 55 | SOURCETYPE_VMF_TGA; 56 | SOURCETYPE_VMF_OTHER; 57 | } 58 | } 59 | 60 | STRING QC_MATERIAL_EXTENSION { } 61 | 62 | SEPARATOR { } 63 | 64 | FILENAME QC_LOADER_MATERIAL_PATH { DIRECTORY; } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/error.cpp: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | 3 | #include "maxon/logger.h" 4 | #include "c4d.h" 5 | 6 | namespace st 7 | { 8 | static const maxon::Id loggerid("com.thatnwp.xNWP.sourcetoolslogger"); 9 | class LoggerImpl; 10 | static LoggerImpl* g_instance; 11 | 12 | class LoggerImpl 13 | { 14 | maxon::LoggerRef _logger; 15 | 16 | public: 17 | static void Write(const maxon::String& msg) 18 | { 19 | if (g_instance == nullptr) 20 | { 21 | g_instance = new LoggerImpl; 22 | g_instance->_logger = maxon::LoggerRef::Create().UncheckedGetValue(); 23 | g_instance->_logger.AddLoggerType(maxon::TARGETAUDIENCE::ALL, maxon::LoggerTypes::Application()).UncheckedGetValue(); 24 | g_instance->_logger.SetName("Source Tools"_s); 25 | maxon::Loggers::Insert(loggerid, g_instance->_logger).UncheckedGetValue(); 26 | const maxon::Int32 BFM_REBUILDCONSOLETREE = 334295845; 27 | SpecialEventAdd(BFM_REBUILDCONSOLETREE); 28 | } 29 | 30 | g_instance->_logger.Write(maxon::TARGETAUDIENCE::ALL, msg, maxon::SourceLocation::NullValue()).UncheckedGetValue(); 31 | } 32 | }; 33 | 34 | void st::iLog(const maxon::String& msg) 35 | { 36 | LoggerImpl::Write(msg); 37 | } 38 | 39 | void st::iLogError(const maxon::String& msg, const char* FILE, const char* FUNC, unsigned int LINE) 40 | { 41 | String m = "ERROR: "_s; m += msg; 42 | m += "\nFILE: "_s; m += FILE; 43 | m += "\nFUNC: "_s; m += FUNC; 44 | m += "\nLINE: "_s; m += maxon::ToString(LINE, nullptr); 45 | 46 | st::iLog(m); 47 | } 48 | 49 | void st::iLogErrorWhat(const maxon::String& WHAT, const char* FILE, const char* FUNC, unsigned int LINE) 50 | { 51 | String m = "ERRORWHAT: "_s; m += WHAT; 52 | m += "\nFILE: "_s; m += FILE; 53 | m += "\nFUNC: "_s; m += FUNC; 54 | m += "\nLINE: "_s; m += maxon::ToString(LINE, nullptr); 55 | 56 | st::iLog(m); 57 | } 58 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/benchmark.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmark.h" 2 | 3 | #include "error.h" 4 | 5 | namespace st 6 | { 7 | Benchmark::Benchmark(const String& name, Bool printOnDestruct, Bool startImmediately) 8 | { 9 | _name = name; 10 | _printOnDestruct = printOnDestruct; 11 | _stopped = true; 12 | _elapsedTime = 0.0; 13 | if (startImmediately) StartBenchmark(); 14 | } 15 | 16 | Benchmark::~Benchmark() 17 | { 18 | if (_printOnDestruct) { 19 | String msg = "Benchmark '" + _name + "' completed in " + GetElapsedTimeFormatted(); 20 | Log(msg); 21 | } 22 | } 23 | 24 | void Benchmark::StopBenchmark() 25 | { 26 | if (_stopped) return; 27 | _stopped = true; 28 | std::chrono::duration tp = std::chrono::steady_clock::now() - _start; 29 | _elapsedTime += Float64(tp.count()); 30 | } 31 | 32 | void Benchmark::StartBenchmark() 33 | { 34 | if (!_stopped) return; 35 | _stopped = false; 36 | _start = std::chrono::steady_clock::now(); 37 | } 38 | 39 | Float64 Benchmark::GetElapsedSeconds() const 40 | { 41 | if (!_stopped) { 42 | std::chrono::duration tp = std::chrono::steady_clock::now() - _start; 43 | return _elapsedTime + Float64(tp.count()); 44 | } else { 45 | return _elapsedTime; 46 | } 47 | } 48 | 49 | String Benchmark::GetElapsedTimeFormatted() const 50 | { 51 | Float64 eTime = GetElapsedSeconds(); 52 | String postFix = " s"_s; 53 | 54 | if (eTime < 1.0) 55 | { 56 | eTime *= 1000.0; 57 | postFix = " ms"_s; 58 | } 59 | 60 | if (eTime < 1.0) 61 | { 62 | eTime *= 1000.0; 63 | postFix = " us"_s; 64 | } 65 | 66 | String rval = maxon::String::FloatToString(Float(eTime), -1, 3); 67 | rval += postFix; 68 | return rval; 69 | } 70 | 71 | Bool Benchmark::IsRunning() const 72 | { 73 | return !_stopped; 74 | } 75 | 76 | void Benchmark::PrintOnDestruct(Bool val) { 77 | _printOnDestruct = val; 78 | } 79 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/main.cpp: -------------------------------------------------------------------------------- 1 | #include "c4d_plugin.h" 2 | #include "c4d_resource.h" 3 | 4 | #include "vtf/vtfloader.h" 5 | #include "smd/smdloader.h" 6 | #include "qc/qcloader.h" 7 | #include "vmt/vmtloader.h" 8 | #include "camio/camioloader.h" 9 | 10 | #include "error.h" 11 | 12 | #define SOURCETOOLS_VERSION_MAJOR 0 13 | #define SOURCETOOLS_VERSION_MINOR 91 14 | #define SOURCETOOLS_VERSION_TAG "dev" 15 | 16 | Bool PluginStart() 17 | { 18 | using namespace st; 19 | 20 | // VTF Loader 21 | if (!vtf::LoaderData::RegisterPlugin()) 22 | { 23 | LogError("Failed to register VTF loader."); 24 | return false; 25 | } 26 | 27 | // SMD Loader 28 | if (!smd::LoaderData::RegisterPlugin()) 29 | { 30 | LogError("Failed to register SMD loader."); 31 | return false; 32 | } 33 | 34 | // QC Loader 35 | if (!qc::LoaderData::RegisterPlugin()) 36 | { 37 | LogError("Failed to register QC loader."); 38 | return false; 39 | } 40 | 41 | // VMT Loader 42 | if (!vmt::LoaderData::RegisterPlugin()) 43 | { 44 | LogError("Failed to register VMT loader."); 45 | return false; 46 | } 47 | 48 | // CamIO Loader 49 | if (!camio::LoaderData::RegisterPlugin()) 50 | { 51 | LogError("Failed to register CamIO Loader."); 52 | return false; 53 | } 54 | 55 | Log("Loaded all sourcetools modules."); 56 | String VersionMessage = "Version: "_s + maxon::ToString(SOURCETOOLS_VERSION_MAJOR, nullptr) 57 | + "."_s + maxon::ToString(SOURCETOOLS_VERSION_MINOR, nullptr) + 58 | maxon::ToString(SOURCETOOLS_VERSION_TAG, nullptr); 59 | #ifdef _DEBUG 60 | VersionMessage += "-debug"; 61 | #endif 62 | #ifdef ST_PROFILING 63 | VersionMessage += "-profiling"; 64 | #endif 65 | Log(VersionMessage); 66 | 67 | return true; 68 | } 69 | 70 | void PluginEnd() 71 | { 72 | } 73 | 74 | Bool PluginMessage(Int32 id, void *data) 75 | { 76 | switch (id) 77 | { 78 | case C4DPL_INIT_SYS: 79 | { 80 | if (g_resource.Init() == false) 81 | { 82 | LogError("Failed to load resources."); 83 | return false; 84 | } 85 | } 86 | } 87 | 88 | return true; 89 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/sharedgrammar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "tao/pegtl.hpp" 4 | 5 | namespace st::shared_grammar 6 | { 7 | using namespace tao; 8 | 9 | /* Junk */ 10 | 11 | struct double_quote 12 | : pegtl::one<'"'> 13 | {}; 14 | 15 | struct whitespace 16 | : pegtl::plus 17 | {}; 18 | 19 | struct whitespace_linefeeds 20 | : pegtl::plus 21 | {}; 22 | 23 | /* Primitives */ 24 | 25 | struct identifier_ext 26 | : pegtl::seq>>> 30 | {}; 31 | 32 | struct filename 33 | : identifier_ext 34 | {}; 35 | 36 | struct filepath 37 | : pegtl::seq>, 38 | pegtl::plus < 39 | pegtl::sor>>> 41 | {}; 42 | 43 | struct integer 44 | : pegtl::seq< 45 | pegtl::opt>, 46 | pegtl::plus> 47 | {}; 48 | 49 | struct floatingpoint 50 | : pegtl::seq< 51 | pegtl::opt>, 52 | pegtl::plus, 53 | pegtl::opt, pegtl::plus>>> 54 | {}; 55 | 56 | template 57 | struct opt_quotes_wrapped 58 | : pegtl::seq < 59 | pegtl::opt, 60 | object, 61 | pegtl::opt> 62 | {}; 63 | 64 | template 65 | struct template_keyvalue_pair 66 | : pegtl::seq, whitespace, opt_quotes_wrapped> 67 | {}; 68 | 69 | template 70 | struct template_opt_class 71 | : pegtl::seq < 72 | opt_quotes_wrapped, 73 | whitespace_linefeeds, 74 | pegtl::opt < 75 | pegtl::one<'{'>, 76 | pegtl::until, 77 | pegtl::sor >>> 78 | {}; 79 | 80 | struct line_comment 81 | : pegtl::seq< 82 | pegtl::string<'/', '/'>, 83 | pegtl::until> 84 | {}; 85 | 86 | struct multiline_comment 87 | : pegtl::seq< 88 | pegtl::string<'/', '*'>, 89 | pegtl::until>> 90 | {}; 91 | 92 | struct comments 93 | : pegtl::sor 94 | {}; 95 | } 96 | -------------------------------------------------------------------------------- /plugins/sourcetools/source/vtf/vtfformat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "maxon/integer.h" 4 | 5 | namespace st::vtf::Types 6 | { 7 | enum class IMAGEFORMAT : UInt32 8 | { 9 | IMAGE_FORMAT_NONE = 0xFFFFFFFF, 10 | IMAGE_FORMAT_RGBA8888 = 0, 11 | IMAGE_FORMAT_ABGR8888, 12 | IMAGE_FORMAT_RGB888, 13 | IMAGE_FORMAT_BGR888, 14 | IMAGE_FORMAT_RGB565, 15 | IMAGE_FORMAT_I8, 16 | IMAGE_FORMAT_IA88, 17 | IMAGE_FORMAT_P8, 18 | IMAGE_FORMAT_A8, 19 | IMAGE_FORMAT_RGB888_BLUESCREEN, 20 | IMAGE_FORMAT_BGR888_BLUESCREEN, 21 | IMAGE_FORMAT_ARGB8888, 22 | IMAGE_FORMAT_BGRA8888, 23 | IMAGE_FORMAT_DXT1, 24 | IMAGE_FORMAT_DXT3, 25 | IMAGE_FORMAT_DXT5, 26 | IMAGE_FORMAT_BGRX8888, 27 | IMAGE_FORMAT_BGR565, 28 | IMAGE_FORMAT_BGRX5551, 29 | IMAGE_FORMAT_BGRA4444, 30 | IMAGE_FORMAT_DXT1_ONEBITALPHA, 31 | IMAGE_FORMAT_BGRA5551, 32 | IMAGE_FORMAT_UV88, 33 | IMAGE_FORMAT_UVWQ8888, 34 | IMAGE_FORMAT_RGBA16161616F, 35 | IMAGE_FORMAT_RGBA16161616, 36 | IMAGE_FORMAT_UVLX8888 37 | }; 38 | 39 | enum class IMAGEFLAGS : UInt32 40 | { 41 | TEXTUREFLAGS_POINTSAMPLE = 0x00000001, 42 | TEXTUREFLAGS_TRILINEAR = 0x00000002, 43 | TEXTUREFLAGS_CLAMPS = 0x00000004, 44 | TEXTUREFLAGS_CLAMPT = 0x00000008, 45 | TEXTUREFLAGS_ANISOTROPIC = 0x00000010, 46 | TEXTUREFLAGS_HINT_DXT5 = 0x00000020, 47 | TEXTUREFLAGS_PWL_CORRECTED = 0x00000040, 48 | TEXTUREFLAGS_NORMAL = 0x00000080, 49 | TEXTUREFLAGS_NOMIP = 0x00000100, 50 | TEXTUREFLAGS_NOLOD = 0x00000200, 51 | TEXTUREFLAGS_ALL_MIPS = 0x00000400, 52 | TEXTUREFLAGS_PROCEDURAL = 0x00000800, 53 | 54 | TEXTUREFLAGS_ONEBITALPHA = 0x00001000, 55 | TEXTUREFLAGS_EIGHTBITALPHA = 0x00002000, 56 | 57 | TEXTUREFLAGS_ENVMAP = 0x00004000, 58 | TEXTUREFLAGS_RENDERTARGET = 0x00008000, 59 | TEXTUREFLAGS_DEPTHRENDERTARGET = 0x00010000, 60 | TEXTUREFLAGS_NODEBUGOVERRIDE = 0x00020000, 61 | TEXTUREFLAGS_SINGLECOPY = 0x00040000, 62 | TEXTUREFLAGS_PRE_SRGB = 0x00080000, 63 | 64 | TEXTUREFLAGS_UNUSED_00100000 = 0x00100000, 65 | TEXTUREFLAGS_UNUSED_00200000 = 0x00200000, 66 | TEXTUREFLAGS_UNUSED_00400000 = 0x00400000, 67 | 68 | TEXTUREFLAGS_NODEPTHBUFFER = 0x00800000, 69 | 70 | TEXTUREFLAGS_UNUSED_01000000 = 0x01000000, 71 | 72 | TEXTUREFLAGS_CLAMPU = 0x02000000, 73 | TEXTUREFLAGS_VERTEXTEXTURE = 0x04000000, 74 | TEXTUREFLAGS_SSBUMP = 0x08000000, 75 | 76 | TEXTUREFLAGS_UNUSED_10000000 = 0x10000000, 77 | 78 | TEXTUREFLAGS_BORDER = 0x20000000, 79 | 80 | TEXTUREFLAGS_UNUSED_40000000 = 0x40000000, 81 | TEXTUREFLAGS_UNUSED_80000000 = 0x80000000 82 | }; 83 | 84 | struct Header 85 | { 86 | UChar signature[4]; 87 | UInt32 version[2]; 88 | UInt32 headerSize; 89 | UInt16 width; 90 | UInt16 height; 91 | IMAGEFLAGS flags; 92 | UInt16 frames; 93 | UInt16 firstFrame; 94 | UChar __padding0[4]; 95 | Float32 reflectivity[3]; 96 | UChar __padding1[4]; 97 | Float32 bumpmapScale; 98 | IMAGEFORMAT highResImageFormat; 99 | UChar mipmapCount; 100 | IMAGEFORMAT lowResImageFormat; 101 | UChar lowResImageWidth; 102 | UChar lowResImageHeight; 103 | 104 | // 7.2+ 105 | UInt16 depth; 106 | 107 | // 7.3+ 108 | UChar __padding2[3]; 109 | UInt32 numResources; 110 | }; 111 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/camio/camioloader.cpp: -------------------------------------------------------------------------------- 1 | #include "camioloader.h" 2 | 3 | #include "camioparser.h" 4 | #include "error.h" 5 | #include "utility.h" 6 | 7 | #include "c4d_symbols.h" 8 | #include "c4d_resource.h" 9 | #include "c4d_baseobject.h" 10 | #include "c4d_basedocument.h" 11 | #include "lib_description.h" 12 | #include "obase.h" 13 | #include "c4d_canimation.h" 14 | 15 | #define MAX_CAMIO_VERSION 1 16 | 17 | namespace st::camio 18 | { 19 | NodeData* LoaderData::Create() 20 | { 21 | return NewObjClear(LoaderData); 22 | } 23 | 24 | Bool LoaderData::Identify(BaseSceneLoader* node, const Filename& name, UChar* probe, Int32 size) 25 | { 26 | return CheckCamIOFileHeader(name); 27 | } 28 | 29 | FILEERROR LoaderData::Load(BaseSceneLoader* node, const Filename& name, BaseDocument* doc, SCENEFILTER filterflags, maxon::String* error, BaseThread* bt) 30 | { 31 | CamIO camFile; 32 | 33 | /* Parse the CamIO File */ 34 | if (!ParseCamIO(name, camFile)) 35 | { 36 | auto msg = GeLoadString(S_PARSE_ERROR, name.GetString()); 37 | LogError(msg); 38 | *error = msg; 39 | return FILEERROR::INVALID; 40 | } 41 | 42 | /* Check version */ 43 | if (camFile.Version > MAX_CAMIO_VERSION) 44 | { 45 | auto msg = GeLoadString(S_CAMIO_BAD_VERSION, 46 | maxon::ToString(camFile.Version, nullptr), 47 | maxon::ToString(MAX_CAMIO_VERSION, nullptr)); 48 | LogError(msg); 49 | *error = msg; 50 | return FILEERROR::INVALID; 51 | } 52 | 53 | /* Create Camera and animation tracks*/ 54 | CameraObject* camera = CameraObject::Alloc(); 55 | doc->InsertObject(camera, nullptr, nullptr); 56 | 57 | CTrack* xTrack, * yTrack, * zTrack, 58 | * xRTrack, * yRTrack, * zRTrack; 59 | CCurve* xCurve, * yCurve, * zCurve, 60 | * xRCurve, * yRCurve, * zRCurve; 61 | 62 | xTrack = CTrack::Alloc(camera, 63 | DescID(DescLevel(ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0), 64 | DescLevel(VECTOR_X, DTYPE_REAL, 0))); 65 | yTrack = CTrack::Alloc(camera, 66 | DescID(DescLevel(ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0), 67 | DescLevel(VECTOR_Y, DTYPE_REAL, 0))); 68 | zTrack = CTrack::Alloc(camera, 69 | DescID(DescLevel(ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0), 70 | DescLevel(VECTOR_Z, DTYPE_REAL, 0))); 71 | xRTrack = CTrack::Alloc(camera, 72 | DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION, DTYPE_VECTOR, 0), 73 | DescLevel(VECTOR_X, DTYPE_REAL, 0))); 74 | yRTrack = CTrack::Alloc(camera, 75 | DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION, DTYPE_VECTOR, 0), 76 | DescLevel(VECTOR_Y, DTYPE_REAL, 0))); 77 | zRTrack = CTrack::Alloc(camera, 78 | DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION, DTYPE_VECTOR, 0), 79 | DescLevel(VECTOR_Z, DTYPE_REAL, 0))); 80 | 81 | camera->InsertTrackSorted(xTrack); 82 | camera->InsertTrackSorted(yTrack); 83 | camera->InsertTrackSorted(zTrack); 84 | camera->InsertTrackSorted(xRTrack); 85 | camera->InsertTrackSorted(yRTrack); 86 | camera->InsertTrackSorted(zRTrack); 87 | 88 | xCurve = xTrack->GetCurve(); 89 | yCurve = yTrack->GetCurve(); 90 | zCurve = zTrack->GetCurve(); 91 | xRCurve = xRTrack->GetCurve(); 92 | yRCurve = yRTrack->GetCurve(); 93 | zRCurve = zRTrack->GetCurve(); 94 | 95 | /* Iterate through each time-step and add a keyframe */ 96 | { 97 | const Float startTime = camFile.Frames[0].time; 98 | auto CreateKeyWithValue = 99 | [startTime](CCurve* c, Float t, Float v) 100 | { 101 | auto k = c->AddKey(BaseTime(t - startTime)); 102 | k->SetValue(c, v); 103 | }; 104 | 105 | for (const auto& frame : camFile.Frames) 106 | { 107 | //Matrix 108 | // no idea if this works, abandoned code TODO: verify this solution? lol 109 | 110 | CreateKeyWithValue(xCurve, frame.time, frame.xPosition); 111 | CreateKeyWithValue(yCurve, frame.time, frame.zPosition); 112 | CreateKeyWithValue(zCurve, frame.time, frame.yPosition); 113 | CreateKeyWithValue(xRCurve, frame.time, DegToRad(frame.zRotation - PI/2)); 114 | CreateKeyWithValue(yRCurve, frame.time, DegToRad(-frame.yRotation)); 115 | CreateKeyWithValue(zRCurve, frame.time, DegToRad(frame.xRotation)); 116 | // TODO: Add fov, shortest path, coordinate system stuffs 117 | } 118 | } 119 | 120 | return FILEERROR::NONE; 121 | } 122 | 123 | Bool LoaderData::RegisterPlugin() 124 | { 125 | return RegisterSceneLoaderPlugin(ID_CAMIOLOADER, "CamIO Loader"_s, 0, LoaderData::Create, maxon::String()); 126 | } 127 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/vmt/vmtloader.cpp: -------------------------------------------------------------------------------- 1 | #include "vmtloader.h" 2 | 3 | #include "vmtparser.h" 4 | #include "error.h" 5 | #include "c4d_symbols.h" 6 | #include "utility.h" 7 | 8 | #include "c4d_basedocument.h" 9 | #include "c4d_resource.h" 10 | #include "c4d_basematerial.h" 11 | #include "mmaterial.h" 12 | #include "c4d_basechannel.h" 13 | #include "xbitmap.h" 14 | #include "lib_description.h" 15 | #include "c4d_reflection.h" 16 | 17 | namespace st::vmt 18 | { 19 | Bool LoaderData::Identify(BaseSceneLoader* node, const Filename& name, UChar* probe, Int32 size) 20 | { 21 | // VMT is an ASCII format, we will identify via extension 22 | return (name.GetSuffix().ToLower() == "vmt") ? true : false; 23 | } 24 | 25 | FILEERROR LoaderData::Load(BaseSceneLoader* node, const Filename& name, BaseDocument* doc, SCENEFILTER filterflags, maxon::String* error, BaseThread* bt) 26 | { 27 | using namespace Types; 28 | ValveMaterialType vmt; 29 | if (!ParseVMT(name, vmt)) 30 | return FILEERROR::INVALID; 31 | 32 | Settings config; 33 | auto Folder = name.GetDirectory(); 34 | config.cdmaterials.push_back(Folder); 35 | 36 | // Look for a materials folder 37 | while ((Folder = Folder.GetDirectory()).IsPopulated()) 38 | { 39 | if (Folder.GetFileString().ToLower() == "materials") 40 | { 41 | config.cdmaterials.push_back(Folder); 42 | break; 43 | } 44 | } 45 | 46 | auto Mat = LoaderData::CreateVMT(vmt, config); 47 | 48 | auto ObjName = name.GetFile(); 49 | ObjName.ClearSuffix(); 50 | Mat->SetName(ObjName.GetString()); 51 | doc->InsertMaterial(Mat); 52 | 53 | return FILEERROR::NONE; 54 | } 55 | 56 | Material* LoaderData::CreateVMT(const ValveMaterialType& vmt, const Settings& config) 57 | { 58 | using pt = Types::ParameterType; 59 | 60 | /* Create Material */ 61 | auto Mat = Material::Alloc(); 62 | 63 | Mat->SetChannelState(CHANNEL_REFLECTION, false); 64 | Mat->GetDataInstance()->SetBool(REFLECTION_LAYER_IMPORTED, true); 65 | 66 | /* Color */ 67 | if (vmt.Parameters.find(pt::BASETEXTURE) != std::end(vmt.Parameters)) 68 | { 69 | auto Filepath = Filename(std::any_cast(vmt.Parameters.at(pt::BASETEXTURE))); 70 | Filepath.SetSuffix(config.BitmapExtension); 71 | if (ResolveLocalFilepath(Filepath, config.cdmaterials)) 72 | { 73 | BaseShader* ColorShader = BaseShader::Alloc(Xbitmap); 74 | ColorShader->SetParameter(BITMAPSHADER_FILENAME, Filepath, DESCFLAGS_SET::NONE); 75 | Mat->SetParameter(MATERIAL_COLOR_SHADER, ColorShader, DESCFLAGS_SET::NONE); 76 | Mat->InsertShader(ColorShader); 77 | 78 | if (vmt.Parameters.find(pt::TRANSLUCENT) != std::end(vmt.Parameters)) 79 | { 80 | if (std::any_cast(vmt.Parameters.at(pt::TRANSLUCENT))) 81 | { 82 | Mat->SetChannelState(CHANNEL_ALPHA, true); 83 | 84 | BaseShader* AlphaShader = BaseShader::Alloc(Xbitmap); 85 | AlphaShader->SetParameter(BITMAPSHADER_FILENAME, Filepath, DESCFLAGS_SET::NONE); 86 | Mat->SetParameter(MATERIAL_ALPHA_SHADER, AlphaShader, DESCFLAGS_SET::NONE); 87 | Mat->InsertShader(AlphaShader); 88 | } 89 | } 90 | } 91 | else 92 | { 93 | LogError("Failed to resolve basetexture filepath: " + Filepath.GetString()); 94 | } 95 | } 96 | 97 | /* BumpMap */ 98 | if (vmt.Parameters.find(pt::BUMPMAP) != std::end(vmt.Parameters)) 99 | { 100 | /* skip for ssbump */ 101 | bool ssbump = false; 102 | if (vmt.Parameters.find(pt::SSBUMP) != std::end(vmt.Parameters)) 103 | ssbump = std::any_cast(vmt.Parameters.at(pt::SSBUMP)); 104 | 105 | if (!ssbump) 106 | { 107 | Mat->SetChannelState(CHANNEL_NORMAL, true); 108 | 109 | auto Filepath = Filename(std::any_cast(vmt.Parameters.at(pt::BUMPMAP))); 110 | Filepath.SetSuffix(config.BitmapExtension); 111 | 112 | if (ResolveLocalFilepath(Filepath, config.cdmaterials)) 113 | { 114 | BaseShader* BumpShader = BaseShader::Alloc(Xbitmap); 115 | 116 | BumpShader->SetParameter(BITMAPSHADER_FILENAME, Filepath, DESCFLAGS_SET::NONE); 117 | Mat->SetParameter(MATERIAL_NORMAL_SHADER, BumpShader, DESCFLAGS_SET::NONE); 118 | Mat->InsertShader(BumpShader); 119 | } 120 | else 121 | { 122 | LogError("Failed to resolve bumpmap filepath: " + Filepath.GetString()); 123 | } 124 | } 125 | } 126 | 127 | return Mat; 128 | } 129 | 130 | NodeData* LoaderData::Create() 131 | { 132 | return NewObjClear(LoaderData); 133 | } 134 | 135 | Bool LoaderData::RegisterPlugin() 136 | { 137 | if (!RegisterSceneLoaderPlugin(ID_VMTLOADER, "Valve Material Type (VMT) Loader"_s, 0, LoaderData::Create, ""_s)) 138 | return false; 139 | 140 | return true; 141 | } 142 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/vmt/vmtparser.cpp: -------------------------------------------------------------------------------- 1 | #include "vmtparser.h" 2 | 3 | #include "vmtformat.h" 4 | #include "tao/pegtl.hpp" 5 | #include "sharedgrammar.h" 6 | #include "error.h" 7 | 8 | namespace st::vmt 9 | { 10 | // TODO: Remove this, should be a simpler solution 11 | // case insensitive string compare 12 | static bool istrcmp(const std::string& str1, const std::string& str2) 13 | { 14 | using namespace std; 15 | if (str1.length() != str2.length()) 16 | return false; 17 | 18 | for (std::uint8_t i = 0; i < str1.length(); ++i) 19 | if (tolower(str1[i]) != tolower(str2[i])) 20 | return false; 21 | 22 | return true; 23 | } 24 | 25 | namespace vmt_grammar 26 | { 27 | using namespace tao; 28 | using namespace shared_grammar; 29 | 30 | /* File Objects */ 31 | struct shadertype : pegtl::identifier 32 | {}; 33 | 34 | struct basetexture_value : filepath 35 | {}; 36 | 37 | struct basetexture : 38 | template_keyvalue_pair, 40 | basetexture_value> 41 | {}; 42 | 43 | struct bumpmap_value : filepath 44 | {}; 45 | 46 | struct bumpmap : 47 | template_keyvalue_pair, 49 | bumpmap_value> 50 | {}; 51 | 52 | struct ssbump_value : integer 53 | {}; 54 | 55 | struct ssbump : 56 | template_keyvalue_pair, 58 | ssbump_value> 59 | {}; 60 | 61 | struct translucent_value : integer 62 | {}; 63 | 64 | struct translucent 65 | : template_keyvalue_pair, 67 | translucent_value> 68 | {}; 69 | 70 | struct shader 71 | : template_opt_class 79 | {}; 80 | 81 | struct vmt_file 82 | : pegtl::until> 89 | {}; 90 | 91 | /* Actions */ 92 | template 93 | struct action 94 | : pegtl::nothing 95 | {}; 96 | 97 | template<> 98 | struct action 99 | { 100 | template 101 | static void apply(const Input& in, ValveMaterialType& vmt) 102 | { 103 | if (istrcmp(in.string(), "character")) 104 | vmt.Shader = Types::ShaderType::CHARACTER; 105 | else if (istrcmp(in.string(), "lightmappedgeneric")) 106 | vmt.Shader = Types::ShaderType::LIGHTMAPPEDGENERIC; 107 | else 108 | { 109 | maxon::String err = "Unknwon shader type: "_s + in.string().c_str(); 110 | LogError(err); 111 | vmt.Shader = Types::ShaderType::UNKNOWN; 112 | } 113 | } 114 | }; 115 | 116 | template<> 117 | struct action 118 | { 119 | template 120 | static void apply(const Input& in, ValveMaterialType& vmt) 121 | { 122 | if (vmt.Parameters.find(Types::ParameterType::BASETEXTURE) != std::end(vmt.Parameters)) 123 | { 124 | LogError("BaseTexture redefinition."); 125 | return; 126 | } 127 | 128 | vmt.Parameters[Types::ParameterType::BASETEXTURE] = String(in.string().c_str()); 129 | } 130 | }; 131 | 132 | template<> 133 | struct action 134 | { 135 | template 136 | static void apply(const Input& in, ValveMaterialType& vmt) 137 | { 138 | if (vmt.Parameters.find(Types::ParameterType::BUMPMAP) != std::end(vmt.Parameters)) 139 | { 140 | LogError("BumpMap redefinition."); 141 | return; 142 | } 143 | 144 | vmt.Parameters[Types::ParameterType::BUMPMAP] = String(in.string().c_str()); 145 | } 146 | }; 147 | 148 | template<> 149 | struct action 150 | { 151 | template 152 | static void apply(const Input& in, ValveMaterialType& vmt) 153 | { 154 | if (vmt.Parameters.find(Types::ParameterType::SSBUMP) != std::end(vmt.Parameters)) 155 | { 156 | LogError("ssbump redefinition."); 157 | return; 158 | } 159 | 160 | vmt.Parameters[Types::ParameterType::SSBUMP] = bool(std::stoi(in.string())); 161 | } 162 | }; 163 | 164 | template<> 165 | struct action 166 | { 167 | template 168 | static void apply(const Input& in, ValveMaterialType& vmt) 169 | { 170 | if (vmt.Parameters.find(Types::ParameterType::TRANSLUCENT) != std::end(vmt.Parameters)) 171 | { 172 | LogError("translucent redefinition."); 173 | return; 174 | } 175 | 176 | vmt.Parameters[Types::ParameterType::TRANSLUCENT] = bool(std::stoi(in.string())); 177 | } 178 | }; 179 | } 180 | 181 | maxon::Bool ParseVMT(const Filename& file, ValveMaterialType& vmt) 182 | { 183 | tao::pegtl::file_input infile(file.GetString().GetCStringCopy()); 184 | 185 | maxon::Bool bOk; 186 | try 187 | { 188 | bOk = tao::pegtl::parse(infile, vmt); 189 | } 190 | catch (tao::pegtl::parse_error& e) 191 | { 192 | LogErrorWhat(e); 193 | return false; 194 | } 195 | catch (tao::pegtl::input_error& e) 196 | { 197 | LogErrorWhat(e); 198 | return false; 199 | } 200 | 201 | /* check for errors */ 202 | if (!bOk) 203 | { 204 | return false; 205 | } 206 | 207 | return true; 208 | } 209 | } -------------------------------------------------------------------------------- /plugins/sourcetools/source/camio/camioparser.cpp: -------------------------------------------------------------------------------- 1 | #include "camioparser.h" 2 | 3 | #include "error.h" 4 | #include "tao/pegtl.hpp" 5 | #include "sharedgrammar.h" 6 | 7 | #include "benchmark.h" 8 | 9 | namespace st::camio 10 | { 11 | namespace grammar 12 | { 13 | using namespace tao::pegtl; 14 | using namespace shared_grammar; 15 | 16 | struct version : integer {}; 17 | struct scaling : identifier_ext {}; 18 | 19 | struct header 20 | : seq< 21 | istring<'a', 'd', 'v', 'a', 'n', 'c', 'e', 'd', 'f', 'x', ' ', 'C', 'a', 'm'>, whitespace_linefeeds, 22 | istring<'v', 'e', 'r', 's', 'i', 'o', 'n'>, whitespace, version, whitespace_linefeeds, 23 | istring<'s', 'c', 'a', 'l', 'e', 'F', 'o', 'v'>, whitespace, scaling, whitespace_linefeeds, 24 | istring<'c', 'h', 'a', 'n', 'n', 'e', 'l', 's', ' ', 't', 'i', 'm', 'e', ' ', 'x', 'P', 'o', 's', 'i', 't', 25 | 'i', 'o', 'n', ' ', 'y', 'P', 'o', 's', 'i', 't', 'i', 'o', 'n', ' ', 'z', 'P', 'o', 's', 'i', 't', 'i', 'o', 26 | 'n', ' ', 'x', 'R', 'o', 't', 'a', 't', 'i', 'o', 'n', ' ', 'y', 'R', 'o', 't', 'a', 't', 'i', 'o', 'n', ' ', 27 | 'z', 'R', 'o', 't', 'a', 't', 'i', 'o', 'n', ' ', 'f', 'o', 'v'>, whitespace_linefeeds, 28 | istring<'D', 'A', 'T', 'A'>> 29 | {}; 30 | 31 | struct time : floatingpoint {}; 32 | struct xPos : floatingpoint {}; 33 | struct yPos : floatingpoint {}; 34 | struct zPos : floatingpoint {}; 35 | struct xRot : floatingpoint {}; 36 | struct yRot : floatingpoint {}; 37 | struct zRot : floatingpoint {}; 38 | struct fov : floatingpoint {}; 39 | 40 | struct frame 41 | : seq 49 | {}; 50 | 51 | struct camio_file 52 | : seq< 53 | header, 54 | until>> 58 | {}; 59 | 60 | /* Actions */ 61 | template 62 | struct action 63 | : nothing 64 | {}; 65 | 66 | template<> 67 | struct action 68 | { 69 | template 70 | static void apply(const Input& in, CamIO& camio) 71 | { 72 | camio.Version = std::stoi(in.string()); 73 | } 74 | }; 75 | 76 | template<> 77 | struct action 78 | { 79 | template 80 | static void apply(const Input& in, CamIO& camio) 81 | { 82 | if (in.string() == "none") 83 | camio.Scaling = Types::SCALETYPE::NONE; 84 | else if (in.string() == "alienSwarm") 85 | camio.Scaling = Types::SCALETYPE::ALIENSWARM; 86 | else 87 | { 88 | String msg = "Unknown Scaling Type: "_s; 89 | msg += String(in.string().c_str()); 90 | LogError(msg); 91 | camio.Scaling = Types::SCALETYPE::UNKNOWN; 92 | } 93 | } 94 | }; 95 | 96 | template<> 97 | struct action