Skip to content

Commit 96958b8

Browse files
committed
cli version for sbsp export
1 parent 3357e64 commit 96958b8

File tree

9 files changed

+303
-1
lines changed

9 files changed

+303
-1
lines changed

.github/workflows/cmake.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ jobs:
6262
name: infiniteExplorer
6363
path: |
6464
${{github.workspace}}/build/infiniteExplorer.exe
65+
${{github.workspace}}/build/infiniteExplorerCLI.exe
6566
${{github.workspace}}/build/detex_LICENSE
6667
6768
- name: Upload a Build Artifact (no FUSE)
@@ -72,4 +73,5 @@ jobs:
7273
name: infiniteExplorer_noFUSE
7374
path: |
7475
${{github.workspace}}/build2/infiniteExplorer.exe
76+
${{github.workspace}}/build2/infiniteExplorerCLI.exe
7577
${{github.workspace}}/build2/detex_LICENSE

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
[submodule "yttrium"]
55
path = 3D/yttrium
66
url = [email protected]:Coreforge/yttrium.git
7+
[submodule "argparse"]
8+
path = argparse
9+
url = https://github.com/p-ranav/argparse

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(INFINITE_OODLE_DLL oo2core_8_win64.dll)
1515
set(FUSE ON)
1616

1717
option(YTTRIUM_3D_VIEWER "Build the 3D viewer" ON)
18+
option(BUILD_CLI_VERSION "Build CLI" ON)
1819

1920

2021
############################################################################
@@ -156,6 +157,10 @@ endif()
156157

157158
target_include_directories(infiniteExplorer PUBLIC .)
158159

160+
if(BUILD_CLI_VERSION)
161+
add_subdirectory(argparse/)
162+
include(cli/CMakeLists.txt)
163+
endif()
159164

160165

161166

ModuleDisplayManager.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ void ModuleDisplayManager::loadPathRecursive(std::string path){
152152

153153
if (dirHandle == INVALID_HANDLE_VALUE) {
154154
logger->log(LOG_LEVEL_WARNING,"Could not open %s\n", path.c_str());
155+
return;
155156
}
156157

157158
do {
@@ -197,6 +198,7 @@ void ModuleDisplayManager::loadPathRecursive(std::string path){
197198
if(!dir){
198199
// something went wrong opening the directory
199200
logger->log(LOG_LEVEL_WARNING,"Failed to open %s\n",path.c_str());
201+
return;
200202
}
201203
struct dirent* ent;
202204
ent = readdir(dir);

argparse

Submodule argparse added at b0930ab

cli/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
add_executable(infiniteExplorerCLI)
2+
3+
target_link_libraries(infiniteExplorerCLI assimp)
4+
set_property(TARGET infiniteExplorerCLI PROPERTY CXX_STANDARD 20)
5+
6+
# CLI source files
7+
8+
target_sources(infiniteExplorerCLI PRIVATE ${CMAKE_CURRENT_LIST_DIR}/main.cpp)
9+
10+
# the exporter code from the 3D folder has to be added separately, since it's compiled into the main executable
11+
target_sources(infiniteExplorerCLI PRIVATE 3D/ExporterBase.cpp)
12+
target_sources(infiniteExplorerCLI PRIVATE 3D/AssImpExporter.cpp)
13+
14+
if(WIN32)
15+
target_sources(infiniteExplorerCLI PRIVATE res/Icon.rc)
16+
endif()
17+
18+
target_include_directories(infiniteExplorerCLI PUBLIC .)
19+
20+
target_link_libraries(infiniteExplorerCLI Infinite)
21+
target_link_libraries(infiniteExplorerCLI argparse)

cli/main.cpp

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
#include <argparse/argparse.hpp>
2+
#include <cstdio>
3+
#include <iostream>
4+
#include <string>
5+
#include <string.h>
6+
#include <vector>
7+
8+
#include "main.h"
9+
10+
#include <libInfinite/logger/ConsoleLogger.h>
11+
#include <libInfinite/tags/TagManager.h>
12+
13+
#include <glm/gtc/quaternion.hpp>
14+
#include <glm/gtx/euler_angles.hpp>
15+
#include <glm/gtx/transform.hpp>
16+
17+
#include <3D/AssImpExporter.h>
18+
19+
20+
#ifdef _WIN64
21+
#include <windows.h>
22+
#include <fileapi.h>
23+
//#include <direct.h>
24+
25+
//#warning WIN64 detected
26+
#endif
27+
28+
#include <dirent.h>
29+
#include <sys/types.h>
30+
#include <sys/stat.h>
31+
#include <fcntl.h>
32+
33+
int main(int argc, char* argv[]){
34+
argparse::ArgumentParser parser("infinteExplorerCLI");
35+
36+
parser.add_argument("-d","--deploy").help("Path which is searched for module files")
37+
.default_value<std::vector<std::string>>({}).append();
38+
int verbosity = 0;
39+
parser.add_argument("-V", "--verbose").help("increase logging verbosity").action([&](const auto &) {++verbosity;}).
40+
append().default_value(false).implicit_value(true).nargs(0);
41+
42+
parser.add_argument("-i", "--globalid").help("global ID of the main tag to load. This is an unsigned 32bit number").scan<'i',uint32_t>();
43+
44+
parser.add_argument("-e", "--export").help("Export data from the tag. Currently only SBSP").default_value(false).implicit_value(true);
45+
46+
parser.add_argument("-o", "--output").help("Output path").default_value("--");
47+
48+
try{
49+
parser.parse_args(argc, argv);
50+
} catch(const std::runtime_error& err){
51+
std::cerr << err.what() << std::endl;
52+
std::cerr << parser;
53+
return -1;
54+
}
55+
56+
FILE* loggerfile;
57+
58+
if(parser.get<std::string>("-o") == "--"){
59+
loggerfile = stderr;
60+
} else {
61+
loggerfile = stdout;
62+
}
63+
64+
int generalLogLevel = std::max(LOG_LEVEL_ERROR - verbosity,0);
65+
ConsoleLogger generalLogger(generalLogLevel, "", loggerfile);
66+
67+
int libInfLogLevel = std::max(LOG_LEVEL_ERROR - verbosity,0);
68+
ConsoleLogger libInfLogger(libInfLogLevel,"[libInfinite] ", loggerfile);
69+
ModuleManager modman(&libInfLogger);
70+
TagManager tagman(&modman,&libInfLogger);
71+
72+
for(auto path : parser.get<std::vector<std::string>>("-d")){
73+
loadPathRecursive(path, &libInfLogger, modman);
74+
}
75+
76+
if(modman.modules.size() == 0){
77+
generalLogger.log(LOG_LEVEL_CRITICAL, "No modules loaded! Aborting\n");
78+
return -1;
79+
}
80+
generalLogger.log(LOG_LEVEL_INFO,"Loaded %d modules\n",modman.modules.size());
81+
modman.buildNodeTree();
82+
83+
uint32_t globalId = 0;
84+
bool globalIdSet = false;
85+
if(auto id = parser.present<uint32_t>("--globalid")){
86+
globalId = *id;
87+
globalIdSet = true;
88+
}
89+
90+
// check if this global ID exists, and get the associated item
91+
if(modman.assetIdItems.contains(globalId) && globalIdSet){
92+
if(parser.get<bool>("-e")){
93+
Tag* tag = tagman.getTag(globalId);
94+
if(modman.assetIdItems[globalId]->tagType == 'sbsp'){
95+
if(exportBSP(dynamic_cast<sbspHandle*>(tag), parser.get<std::string>("-o"), &generalLogger)){
96+
return -1;
97+
}
98+
}
99+
}
100+
} else if(globalIdSet) {
101+
generalLogger.log(LOG_LEVEL_CRITICAL, "That global ID doesn't exist!\n");
102+
return -1;
103+
}
104+
105+
}
106+
107+
int exportBSP(sbspHandle* handle, std::string out, Logger* logger){
108+
if(handle == nullptr){
109+
logger->log(LOG_LEVEL_CRITICAL, "No BSP tag handle to export!\n");
110+
return -1;
111+
}
112+
AssImpExporter exporter;
113+
exporter.setLogger(logger);
114+
exporter.newScene();
115+
116+
int c = handle->getGeoInstanceCount();
117+
int f = 0;
118+
int i;
119+
for(i = 0; i < c; i++){
120+
auto inst = handle->getGeoInstanceInfo(i);
121+
if(inst.geo == nullptr){
122+
// later, maybe add an error here (maybe like source?), but for now, just skip it
123+
continue;
124+
}
125+
if(inst.mesh_flags_override & MESH_FLAGS_OVERRIDE_MESH_IS_CUSTOM_SHADOW_CASTER){
126+
// just don't to anything with shadowcasters for now. Other wizards are allowed though.
127+
continue;
128+
}
129+
f++;
130+
131+
auto meshdata = inst.geo->getMeshData(inst.meshIndex);
132+
133+
glm::mat3 meshrot_mat(meshdata.forward, meshdata.left, meshdata.up);
134+
glm::mat4 meshposmat = glm::translate(meshdata.position);
135+
glm::mat4 meshscalemat = glm::scale(meshdata.scale);
136+
glm::mat4 meshtransform = meshposmat * glm::mat4(meshrot_mat) * meshscalemat;
137+
138+
139+
glm::mat3 rot_mat(inst.forward, inst.left, inst.up);
140+
//glm::mat3 rot_mat(glm::vec3(inst.up.x,inst.forward.x,inst.left.x), glm::vec3(inst.up.y,inst.forward.y,inst.left.y), glm::vec3(inst.up.z,inst.forward.z,inst.left.z));
141+
//glm::mat3 rot_mat(inst.up, inst.forward, inst.left);
142+
glm::mat4 bigrotmat(rot_mat);
143+
//bigrotmat = glm::transpose(bigrotmat);
144+
glm::vec3 rotation = glm::eulerAngles(glm::quat_cast(rot_mat));
145+
rotation = glm::degrees(rotation);
146+
glm::vec4 rotatedPos = glm::rotate(glm::radians(-90.0f), glm::vec3(1.0,0.0,0.0)) * glm::vec4(inst.position,1.0f);
147+
//globalWindowPointer->viewer3D.addRenderGeo(&inst.geo->geoHandle, inst.meshIndex, inst.position, bigrotmat, -inst.scale); // glm::vec3(rotatedPos.x,rotatedPos.y,rotatedPos.z)
148+
exporter.addRenderGeo(&inst.geo->geoHandle, inst.meshIndex, inst.position, rot_mat, inst.scale,"owo");
149+
}
150+
logger->log(LOG_LEVEL_INFO, "%d Instances in total, %d included in export (shadowcasters are excluded)\n", i, f);
151+
exporter.exportScene(out);
152+
return 0;
153+
}
154+
// duplicate code, since this is currently in ModuleDisplayManager, which is only used in the GUI
155+
156+
void loadPathRecursive(std::string path, Logger* logger, ModuleManager& modMan){
157+
158+
// this has to be done differently on POSIX-compliant systems and /windows/ ...sigh
159+
160+
#ifdef _WIN64
161+
// windows version
162+
WIN32_FIND_DATA find;
163+
HANDLE dirHandle;
164+
165+
std::string searchPath = path + "/*";
166+
167+
dirHandle = FindFirstFile(searchPath.c_str(), &find);
168+
169+
if (dirHandle == INVALID_HANDLE_VALUE) {
170+
logger->log(LOG_LEVEL_WARNING,"Could not open %s\n", path.c_str());
171+
return;
172+
}
173+
174+
do {
175+
std::string cPath = path + "\\" + find.cFileName;
176+
//printf("Found %s\n",cPath.c_str());
177+
if (!(strncmp(find.cFileName, ".", 2) && strncmp(find.cFileName, "..", 3))) {
178+
// . or .., skip those
179+
continue;
180+
}
181+
182+
if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
183+
// is a directory
184+
//printf("This is a directory\n");
185+
loadPathRecursive(cPath, logger, modMan);
186+
187+
// don't do the other stuff, which is only for files
188+
continue;
189+
}
190+
191+
// this is only for files
192+
193+
std::string name(find.cFileName);
194+
195+
// all of this can just be copied from the posix version
196+
if (name.size() < 7) {
197+
// name is too short
198+
continue;
199+
}
200+
if (name.substr(name.size() - 7, 7) == ".module") {
201+
// extension should match
202+
if (modMan.addModule(cPath.c_str())) {
203+
// the module couldn't be loaded
204+
logger->log(LOG_LEVEL_ERROR,"Failed to load module %s, skipping!\n", cPath.c_str());
205+
}
206+
}
207+
208+
209+
} while (FindNextFile(dirHandle,&find));
210+
#else
211+
// the posix version
212+
DIR* dir;
213+
dir = opendir(path.c_str()); // open the current directory
214+
if(!dir){
215+
// something went wrong opening the directory
216+
logger->log(LOG_LEVEL_WARNING,"Failed to open %s\n",path.c_str());
217+
return;
218+
}
219+
struct dirent* ent;
220+
ent = readdir(dir);
221+
struct stat buf;
222+
while(ent){
223+
// for every entry
224+
std::string cPath = path + "/" + ent->d_name;
225+
if(stat(cPath.c_str(),&buf)){
226+
// something went wrong with stat
227+
// report the error and just skip this entry
228+
logger->log(LOG_LEVEL_WARNING,"Failed to stat %s!\n",cPath.c_str()); // warning because it might not be an actual issue
229+
goto next; // skip to the next entry
230+
continue;
231+
}
232+
if(S_ISDIR(buf.st_mode)){
233+
// another directory, check that one too
234+
if(strncmp(ent->d_name,".",2) && strncmp(ent->d_name,"..",3)){
235+
//printf("Looking in %s\n",cPath.c_str());
236+
loadPathRecursive(cPath, logger, modMan);
237+
}
238+
239+
}
240+
if(S_ISREG(buf.st_mode)){
241+
// regular file, but that doesn't mean it's a module
242+
// first check the file extension (.module, the last 7 characters of the name)
243+
std::string name(ent->d_name);
244+
if(name.size() < 7){
245+
// name is too short
246+
goto next;
247+
}
248+
if(name.substr(name.size() - 7, 7) == ".module"){
249+
// extension should match
250+
if(modMan.addModule(cPath.c_str())){
251+
// the module couldn't be loaded
252+
logger->log(LOG_LEVEL_ERROR,"Failed to load module %s, skipping!\n",cPath.c_str());
253+
}
254+
}
255+
}
256+
next:
257+
ent = readdir(dir); // next entry
258+
}
259+
#endif
260+
}

cli/main.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <libInfinite/module/ModuleManager.h>
5+
#include <libInfinite/tags/handles/sbspHandle.h>
6+
7+
void loadPathRecursive(std::string path, Logger* logger, ModuleManager& modMan);
8+
int exportBSP(sbspHandle* handle, std::string out, Logger* logger);

0 commit comments

Comments
 (0)