3 #include <Strings/components/utils/io/io.h>
4 #include <Strings/components/utils/string/string.h>
5 #include <Strings/components/utils/converters/converters.h>
6 #include <Strings/components/logger/logger.h>
8 #include <HEKGuerilla/components/tags/importers/bitmap/bitmap.h>
9 #include <HEKGuerilla/components/tags/tags.h>
10 #include <HEKGuerilla/components/tags/fields/block/block.h>
11 #include <HEKGuerilla/components/tags/fields/tagref/tagref.h>
12 #include <HEKGuerilla/components/tags/fields/enum/enum.h>
13 #include <HEKGuerilla/components/tags/fields/color/color.h>
14 #include <HEKGuerilla/components/tags/fields/float32/float32.h>
15 #include <HEKGuerilla/components/settings/config/config.h>
17 #include "../ToolCommand.hpp"
18 #include "../console.h"
22 #ifdef TOOL_LIB_EXPORTS
23 #define TOOL_LIB_API __declspec(dllexport)
25 #define TOOL_LIB_API __declspec(dllimport)
37 std::vector<std::string> diffuse_texture_keywords = {
38 "diffuse",
"basecolor",
"color",
"albedo"
41 std::vector<std::string> normal_texture_keywords = {
45 std::vector<std::string> roughness_texture_keywords = {
49 std::vector<std::string> specular_texture_keywords = {
53 std::vector<std::string> emissive_texture_keywords = {
54 "emissive",
"glow",
"illum"
57 std::vector<std::string> metallic_texture_keywords = {
65 syntax =
"material <directory> [overwrite] [skip bitmap import]";
66 description =
"creates a pbr material from a texture set. assigns textures based on guesses from names. materials will generally be imperfect and require fine tuning.";
69 int execute(std::vector<std::string> args)
73 BlamStrings::Logger::LogEvent(
"no input directory path was provided, cannot compile bitmaps", BlamLogLevel::Warning);
79 BlamStrings::Logger::LogEvent(
"too many arguments specified - skipping import. check your input and try again. "
80 "for additional help, use 'tool.exe help material'.", BlamLogLevel::Warning);
86 std::string import_base_dir = BlamStrings::Utils::IO::NormalizePath(project_root +
"data/");
87 std::string output_base_dir = BlamStrings::Utils::IO::NormalizePath(project_root +
"tags/");
89 bool overwrite =
false;
90 bool skip_bitmaps =
false;
91 std::string input_directory =
"";
92 std::string output_directory =
"";
93 std::string material_tag_name =
"";
99 if (BlamStrings::Converters::StringToBool(args[1]))
105 if (args.size() >= 3)
107 if (BlamStrings::Converters::StringToBool(args[2]))
113 input_directory = BlamStrings::Utils::IO::NormalizePath(import_base_dir + args[0]);
114 output_directory = BlamStrings::Utils::IO::NormalizePath(output_base_dir + args[0]);
115 material_tag_name = BlamStrings::Utils::IO::GetFileName(output_directory);
120 if (!bitmaps_command)
122 BlamStrings::Logger::LogEvent(
"cannot resolve bitmaps command - this is a bug and should be reported", BlamLogLevel::Warning);
126 BlamStrings::Logger::LogEvent(
"step 1: bitmap import");
130 if (bitmaps_command->
execute({ args.at(0),
"true" }) != 0)
132 BlamStrings::Logger::LogEvent(
"bitmaps command execution returned non-zero, bitmaps may not be imported", BlamLogLevel::Warning);
136 BlamStrings::Logger::LogEvent(
"step 2: material creation");
138 if (BlamStrings::Utils::IO::FileExists(output_directory +
"/" + material_tag_name +
".material") && !overwrite)
140 BlamStrings::Logger::LogEvent(
"not creating new material tag, file already exists - to force material creation anyway, set override to true (will destroy existing tag!)", BlamLogLevel::Warning);
144 Guerilla::Tags::LoadPlugins();
146 std::vector<std::string> bitmap_paths = std::vector<std::string>();
148 for (std::string file_path : BlamStrings::Utils::IO::GetFileList(output_directory))
150 if (!str_tolower(file_path).ends_with(
".bitmap"))
155 bitmap_paths.push_back(file_path);
158 BlamPlugin* material_plugin = Guerilla::Tags::GetPlugin(
"material");
160 if (!material_plugin)
162 BlamStrings::Logger::LogEvent(
"cannot create material: cannot locate material plugin", WSV_WARNING);
166 BlamTag* tag = material_plugin->CreateNewTag();
168 tag->file_path = output_directory +
"/" + material_tag_name +
".material";
170 BlamTagField_Block* pbr_material_block = tag->GetField<BlamTagField_Block>(
"pbr_material");
172 if (!pbr_material_block)
174 BlamStrings::Logger::LogEvent(
"cannot create material: material plugin is missing a pbr_material block", WSV_WARNING);
178 pbr_material_block->AddEntry();
179 BlamTagBlockEntry* entry = pbr_material_block->entries.at(0);
180 BlamTagField_Block* textures_block = entry->GetField<BlamTagField_Block>(
"textures");
184 BlamStrings::Logger::LogEvent(
"cannot create material: pbr_material block is missing a textures block", WSV_WARNING);
188 std::string diffuse =
"";
189 std::string normal =
"";
190 std::string specular =
"";
191 std::string roughness =
"";
192 std::string emissive =
"";
193 std::string metallic =
"";
195 for (std::string texture_file : bitmap_paths)
197 std::string tag_path = str_replace(texture_file, output_base_dir,
"");
198 std::string tag_name = BlamStrings::Utils::IO::GetFileName(tag_path);
200 if (diffuse.length() == 0 && BlamStrings::Utils::String::ContainsAny(tag_name, diffuse_texture_keywords,
true))
203 if (normal.length() == 0 && BlamStrings::Utils::String::ContainsAny(tag_name, normal_texture_keywords,
true))
206 if (specular.length() == 0 && BlamStrings::Utils::String::ContainsAny(tag_name, specular_texture_keywords,
true))
209 if (roughness.length() == 0 && BlamStrings::Utils::String::ContainsAny(tag_name, roughness_texture_keywords,
true))
210 roughness = tag_path;
212 if (emissive.length() == 0 && BlamStrings::Utils::String::ContainsAny(tag_name, emissive_texture_keywords,
true))
215 if (metallic.length() == 0 && BlamStrings::Utils::String::ContainsAny(tag_name, metallic_texture_keywords,
true))
228 BlamTagField_Float32* metalness = entry->GetField<BlamTagField_Float32>(
"metalness");
229 BlamTagField_Float32* roughness = entry->GetField<BlamTagField_Float32>(
"roughness");
230 BlamTagField_Color* emissive_color = entry->GetField<BlamTagField_Color>(
"emissive_color");
232 if (metalness) metalness->value = 0.5f;
233 if (roughness) roughness->value = 0.5f;
234 if (emissive_color) emissive_color->value = BlamColor(0, 0, 0, 0);
237 if (!Guerilla::Tags::SaveTag(tag))
239 BlamStrings::Logger::LogEvent(
"failed to save material tag - see log for details", WSV_WARNING);
242 Guerilla::Tags::ReleasePlugins();
244 BlamStrings::Logger::LogEvent(
"finished.");
250 if (!block->AddEntry())
252 BlamStrings::Logger::LogEvent(
"failed to add material entry for '" + type +
"': add entry failed", WSV_WARNING);
256 BlamTagBlockEntry* entry = block->entries.at(block->entries.size() - 1);
259 BlamTagField_Enum* texture_type = entry->GetField<BlamTagField_Enum>(
"texture_type", BlamTagFieldType::Enum32);
260 BlamTagField_Tagref* texture = entry->GetField<BlamTagField_Tagref>(
"texture");
262 if (!texture_type || !texture)
264 BlamStrings::Logger::LogEvent(
"failed to add material entry for '" + type
265 +
"': missing texture_type (enum32) and/or texture (tagref) fields", WSV_WARNING);
269 texture_type->current_option = type;
270 texture->referenced_tag_class =
"bitm";
271 texture->referenced_tag_path = tag;