Skip to content

Commit 42808a0

Browse files
committed
[frontend] AssimpImporter: Drastically improve UI
1 parent 35e5d01 commit 42808a0

File tree

2 files changed

+217
-49
lines changed

2 files changed

+217
-49
lines changed

source/frontend/editors/AssimpImporter.cpp

Lines changed: 212 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#include "AssimpImporter.hpp"
22
#include <glm/gtc/type_ptr.hpp>
3+
#include <glm/vec3.hpp>
34
#include <rsl/Defer.hpp>
45

56
#include <frontend/legacy_editor/EditorWindow.hpp>
67
#include <frontend/root.hpp>
8+
#include <frontend/widgets/PropertyEditorWidget.hpp>
79

810
namespace riistudio::frontend {
911

@@ -51,9 +53,19 @@ void ImporterSettings(librii::assimp2rhst::Settings& ctx) {
5153
// aiProcess_Debone - TODO
5254
// aiProcess_GlobalScale
5355
ImGui::InputFloat("Model Scale"_j, &ctx.mMagnification);
54-
ImGui::Checkbox("Emulate BrawlBox Model Scale (This is incorrect and goes "
55-
"against the COLLADA (.dae) specification but may be useful)",
56-
&ctx.mIgnoreRootTransform);
56+
57+
if (ImGui::Checkbox("Emulate BrawlBox Model Scale",
58+
&ctx.mIgnoreRootTransform)) {
59+
// Checkbox clicked, no need to show popup
60+
} else if (ImGui::IsItemHovered()) {
61+
ImGui::BeginTooltip();
62+
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 20.0f);
63+
ImGui::TextUnformatted("This is incorrect and goes against the COLLADA "
64+
"(.dae) specification but may be useful");
65+
ImGui::PopTextWrapPos();
66+
ImGui::EndTooltip();
67+
}
68+
5769
// aiProcess_ForceGenNormals - TODO
5870
// aiProcess_DropNormals - TODO
5971

@@ -63,15 +75,44 @@ void ImporterSettings(librii::assimp2rhst::Settings& ctx) {
6375

6476
void MipMapSettings(librii::assimp2rhst::Settings& ctx) {
6577
ImGui::Checkbox("Generate Mipmaps"_j, &ctx.mGenerateMipMaps);
78+
if (ImGui::IsItemHovered()) {
79+
ImGui::BeginTooltip();
80+
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 20.0f);
81+
ImGui::TextUnformatted(
82+
"Mipmaps are pre-calculated, optimized texture versions at different "
83+
"resolutions that improve rendering quality and performance. Strongly "
84+
"recommended to keep enabled for better visual quality at different "
85+
"distances.");
86+
ImGui::PopTextWrapPos();
87+
ImGui::EndTooltip();
88+
}
6689
{
6790
util::ConditionalActive g(ctx.mGenerateMipMaps);
6891
ImGui::Indent(50);
6992
ImGui::SliderInt("Minimum mipmap dimension."_j, &ctx.mMinMipDimension, 1,
7093
512);
94+
if (ImGui::IsItemHovered()) {
95+
ImGui::BeginTooltip();
96+
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 20.0f);
97+
ImGui::TextUnformatted("Default: 32 pixels. We won't generate mipmap LOD "
98+
"levels smaller than this dimension.");
99+
ImGui::PopTextWrapPos();
100+
ImGui::EndTooltip();
101+
}
71102
ctx.mMinMipDimension =
72103
librii::assimp2rhst::ClampMipMapDimension(ctx.mMinMipDimension);
73104

74105
ImGui::SliderInt("Maximum number of mipmaps."_j, &ctx.mMaxMipCount, 0, 8);
106+
if (ImGui::IsItemHovered()) {
107+
ImGui::BeginTooltip();
108+
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 20.0f);
109+
ImGui::TextUnformatted(
110+
"Default: 5. We won't generate more than this many LOD levels, even "
111+
"if the smallest LOD level is above our minimum mip dimension (for "
112+
"instance on a very large image).");
113+
ImGui::PopTextWrapPos();
114+
ImGui::EndTooltip();
115+
}
75116

76117
ImGui::Indent(-50);
77118
}
@@ -124,25 +165,63 @@ void MeshSettings(librii::assimp2rhst::Settings& ctx) {
124165
}
125166

126167
void MaskSettings(librii::assimp2rhst::Settings& ctx) {
127-
ImGui::CheckboxFlags((const char*)ICON_FA_SORT_AMOUNT_UP u8" Vertex Normals",
128-
&ctx.mDataToInclude, aiComponent_NORMALS);
129-
// aiComponent_TANGENTS_AND_BITANGENTS: Unsupported
130-
ImGui::CheckboxFlags((const char*)ICON_FA_PALETTE u8" Vertex Colors",
131-
&ctx.mDataToInclude, aiComponent_COLORS);
132-
ImGui::CheckboxFlags((const char*)ICON_FA_GLOBE u8" UV Maps",
133-
&ctx.mDataToInclude, aiComponent_TEXCOORDS);
134-
ImGui::CheckboxFlags((const char*)ICON_FA_BONE u8" Bone Weights",
135-
&ctx.mDataToInclude, aiComponent_BONEWEIGHTS);
136-
// aiComponent_ANIMATIONS: Unsupported
137-
// TODO: aiComponent_TEXTURES: Unsupported
138-
// aiComponent_LIGHTS: Unsupported
139-
// aiComponent_CAMERAS: Unsupported
140-
ImGui::CheckboxFlags((const char*)ICON_FA_PROJECT_DIAGRAM u8" Meshes",
141-
&ctx.mDataToInclude, aiComponent_MESHES);
142-
ImGui::CheckboxFlags((const char*)ICON_FA_PAINT_BRUSH u8" Materials",
143-
&ctx.mDataToInclude, aiComponent_MATERIALS);
168+
if (ImGui::BeginTable("DataToImportTable", 2, ImGuiTableFlags_Borders)) {
169+
ImGui::TableSetupColumn("Component", ImGuiTableColumnFlags_WidthFixed);
170+
ImGui::TableSetupColumn("Include", ImGuiTableColumnFlags_WidthStretch);
171+
ImGui::TableHeadersRow();
172+
173+
ImGui::TableNextRow();
174+
ImGui::TableNextColumn();
175+
ImGui::TextUnformatted(
176+
(const char*)ICON_FA_SORT_AMOUNT_UP u8" Vertex Normals");
177+
ImGui::TableNextColumn();
178+
ImGui::CheckboxFlags("##normals", &ctx.mDataToInclude, aiComponent_NORMALS);
179+
180+
ImGui::TableNextRow();
181+
ImGui::TableNextColumn();
182+
ImGui::TextUnformatted((const char*)ICON_FA_PALETTE u8" Vertex Colors");
183+
ImGui::TableNextColumn();
184+
ImGui::CheckboxFlags("##colors", &ctx.mDataToInclude, aiComponent_COLORS);
185+
186+
ImGui::TableNextRow();
187+
ImGui::TableNextColumn();
188+
ImGui::TextUnformatted((const char*)ICON_FA_GLOBE u8" UV Maps");
189+
ImGui::TableNextColumn();
190+
ImGui::CheckboxFlags("##uvmaps", &ctx.mDataToInclude,
191+
aiComponent_TEXCOORDS);
192+
193+
ImGui::TableNextRow();
194+
ImGui::TableNextColumn();
195+
ImGui::TextUnformatted((const char*)ICON_FA_BONE u8" Bone Weights");
196+
ImGui::TableNextColumn();
197+
ImGui::CheckboxFlags("##bones", &ctx.mDataToInclude,
198+
aiComponent_BONEWEIGHTS);
199+
200+
ImGui::TableNextRow();
201+
ImGui::TableNextColumn();
202+
ImGui::TextUnformatted((const char*)ICON_FA_PROJECT_DIAGRAM u8" Meshes");
203+
ImGui::TableNextColumn();
204+
ImGui::CheckboxFlags("##meshes", &ctx.mDataToInclude, aiComponent_MESHES);
205+
206+
ImGui::TableNextRow();
207+
ImGui::TableNextColumn();
208+
ImGui::TextUnformatted((const char*)ICON_FA_PAINT_BRUSH u8" Materials");
209+
ImGui::TableNextColumn();
210+
ImGui::CheckboxFlags("##materials", &ctx.mDataToInclude,
211+
aiComponent_MATERIALS);
212+
213+
ImGui::EndTable();
214+
}
215+
216+
// Note: These components are unsupported:
217+
// - aiComponent_TANGENTS_AND_BITANGENTS
218+
// - aiComponent_ANIMATIONS
219+
// - aiComponent_TEXTURES (TODO)
220+
// - aiComponent_LIGHTS
221+
// - aiComponent_CAMERAS
144222
}
145-
void MeshOptimizationSettings(librii::assimp2rhst::Settings& ctx, bool& tristrip) {
223+
void MeshOptimizationSettings(librii::assimp2rhst::Settings& ctx,
224+
bool& tristrip) {
146225
if (ImGui::BeginChild("HelpBox3",
147226
ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 1.5f),
148227
true, ImGuiWindowFlags_NoScrollbar)) {
@@ -162,6 +241,116 @@ void MeshOptimizationSettings(librii::assimp2rhst::Settings& ctx, bool& tristrip
162241
}
163242
} // namespace
164243

244+
class AssimpEditorTabSheet {
245+
public:
246+
void Draw(std::function<void(void)> draw) {
247+
std::vector<std::string> icons{(const char*)ICON_FA_EXPAND_ARROWS_ALT,
248+
(const char*)ICON_FA_IMAGES,
249+
(const char*)ICON_FA_BRUSH,
250+
(const char*)ICON_FA_PROJECT_DIAGRAM,
251+
(const char*)ICON_FA_TRASH,
252+
(const char*)ICON_FA_PROJECT_DIAGRAM};
253+
std::vector<const char*> labels{"Scale",
254+
"Mip Maps",
255+
"Material Settings",
256+
"Pre-BRRES Optimization",
257+
"Data to Import",
258+
"BRRES Optimization"};
259+
std::vector<ImVec4> iconColors{
260+
ImVec4(0.5f, 0.8f, 1.0f, 1.0f), // Blue for Scale
261+
ImVec4(1.0f, 0.5f, 0.8f, 1.0f), // Pink for Mip Maps
262+
ImVec4(0.8f, 0.6f, 0.2f, 1.0f), // Orange for Material Settings
263+
ImVec4(0.2f, 0.8f, 0.4f, 1.0f), // Green for Pre-BRRES Optimization
264+
ImVec4(1.0f, 0.3f, 0.3f, 1.0f), // Red for Data to Import
265+
ImVec4(0.4f, 0.7f, 0.9f, 1.0f) // Light blue for BRRES Optimization
266+
};
267+
268+
std::function<bool(int)> drawTab = [&](int index) {
269+
switch (index) {
270+
case 0:
271+
ImporterSettings(ctx);
272+
break;
273+
case 1:
274+
MipMapSettings(ctx);
275+
break;
276+
case 2:
277+
MaterialSettings(ctx);
278+
break;
279+
case 3:
280+
MeshSettings(ctx);
281+
break;
282+
case 4:
283+
MaskSettings(ctx);
284+
break;
285+
case 5:
286+
MeshOptimizationSettings(ctx, tristrip);
287+
break;
288+
default:
289+
return false;
290+
}
291+
return true;
292+
};
293+
std::function<void(int)> drawTabTitle = [&](int index) {
294+
bool isNonDefault = false;
295+
switch (index) {
296+
case 0:
297+
isNonDefault = ctx.mMagnification != 1.0f || ctx.mIgnoreRootTransform;
298+
break;
299+
case 1:
300+
isNonDefault = !ctx.mGenerateMipMaps || ctx.mMinMipDimension != 32 ||
301+
ctx.mMaxMipCount != 5;
302+
break;
303+
case 2:
304+
isNonDefault =
305+
!ctx.mAutoTransparent ||
306+
(ctx.mAiFlags & aiProcess_RemoveRedundantMaterials) == 0 ||
307+
ctx.mAiFlags & aiProcess_TransformUVCoords ||
308+
ctx.mModelTint != glm::vec3(1.0f);
309+
break;
310+
case 3:
311+
isNonDefault = ctx.mAiFlags != (librii::assimp2rhst::AlwaysFlags |
312+
librii::assimp2rhst::DefaultFlags);
313+
break;
314+
case 4:
315+
isNonDefault =
316+
ctx.mDataToInclude != librii::assimp2rhst::DefaultInclusionMask();
317+
break;
318+
case 5:
319+
isNonDefault = !tristrip;
320+
break;
321+
}
322+
323+
// Draw colored icon
324+
ImGui::PushStyleColor(ImGuiCol_Text,
325+
ImGui::ColorConvertFloat4ToU32(iconColors[index]));
326+
ImGui::TextUnformatted(icons[index].c_str());
327+
ImGui::PopStyleColor();
328+
329+
ImGui::SameLine(0, 0);
330+
331+
// Draw label with conditional yellow color for non-default settings
332+
if (isNonDefault) {
333+
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 0, 255));
334+
ImGui::TextUnformatted(labels[index]);
335+
ImGui::PopStyleColor();
336+
} else {
337+
ImGui::Text(" %s", labels[index]);
338+
}
339+
};
340+
341+
std::vector<std::string> titles(icons.size());
342+
for (size_t i = 0; i < icons.size(); i++) {
343+
titles[i] = std::string(icons[i]) + std::string(" ") + labels[i];
344+
}
345+
346+
DrawPropertyEditorWidgetV2_Header(m_state, false);
347+
DrawPropertyEditorWidgetV3_Body(m_state, drawTab, drawTabTitle, titles);
348+
}
349+
PropertyEditorState& m_state;
350+
librii::assimp2rhst::Settings& ctx;
351+
bool& tristrip;
352+
};
353+
165354
void AssimpEditorPropertyGrid::Draw(librii::assimp2rhst::Settings& ctx,
166355
bool& tristrip) {
167356
if (ImGui::BeginChild("HelpBox",
@@ -177,34 +366,8 @@ void AssimpEditorPropertyGrid::Draw(librii::assimp2rhst::Settings& ctx,
177366
}
178367
ImGui::EndChild();
179368

180-
if (ImGui::CollapsingHeader("Importing Settings"_j,
181-
ImGuiTreeNodeFlags_DefaultOpen)) {
182-
ImporterSettings(ctx);
183-
}
184-
185-
if (ImGui::CollapsingHeader((const char*)ICON_FA_IMAGES u8" Mip Maps",
186-
ImGuiTreeNodeFlags_DefaultOpen)) {
187-
MipMapSettings(ctx);
188-
}
189-
if (ImGui::CollapsingHeader((const char*)ICON_FA_BRUSH u8" Material Settings",
190-
ImGuiTreeNodeFlags_DefaultOpen)) {
191-
MaterialSettings(ctx);
192-
}
193-
if (ImGui::CollapsingHeader(
194-
(const char*)ICON_FA_PROJECT_DIAGRAM u8" Mesh Settings",
195-
ImGuiTreeNodeFlags_DefaultOpen)) {
196-
MeshSettings(ctx);
197-
}
198-
if (ImGui::CollapsingHeader(
199-
(const char*)ICON_FA_PROJECT_DIAGRAM u8" Data to Import",
200-
ImGuiTreeNodeFlags_DefaultOpen)) {
201-
MaskSettings(ctx);
202-
}
203-
if (ImGui::CollapsingHeader(
204-
(const char*)ICON_FA_PROJECT_DIAGRAM u8" Mesh Optimization",
205-
ImGuiTreeNodeFlags_DefaultOpen)) {
206-
MeshOptimizationSettings(ctx, tristrip);
207-
}
369+
AssimpEditorTabSheet sheet{m_propState, ctx, tristrip};
370+
sheet.Draw([]() {});
208371
}
209372

210373
void AssimpImporter::draw_() {

source/frontend/editors/AssimpImporter.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@
1111
#include <plugins/g3d/collection.hpp>
1212
#include <plugins/j3d/Scene.hpp>
1313

14+
#include <frontend/widgets/PropertyEditorWidget.hpp>
15+
1416
namespace riistudio::frontend {
1517

1618
class AssimpEditorPropertyGrid {
1719
public:
1820
void Draw(librii::assimp2rhst::Settings& x, bool& tristrip);
21+
22+
private:
23+
PropertyEditorState m_propState{};
1924
};
2025

2126
class AssimpImporter : public frontend::StudioWindow {

0 commit comments

Comments
 (0)