@@ -11,6 +11,7 @@ module vk_gltf_viewer.imgui.TaskCollector;
11
11
import imgui.math;
12
12
13
13
import vk_gltf_viewer.global;
14
+ import vk_gltf_viewer.gltf.util;
14
15
import vk_gltf_viewer.gui.dialog;
15
16
import vk_gltf_viewer.helpers.concepts;
16
17
import vk_gltf_viewer.helpers.fastgltf;
@@ -1013,10 +1014,28 @@ void vk_gltf_viewer::control::ImGuiTaskCollector::materialVariants(gltf::AssetEx
1013
1014
selected = static_cast <int >(*assetExtended.imGuiSelectedMaterialVariantsIndex );
1014
1015
}
1015
1016
1016
- for (const auto &[i, variantName] : assetExtended.asset .materialVariants | ranges::views::enumerate) {
1017
- if (ImGui::RadioButton (variantName.c_str (), &selected, i)) {
1017
+ for (const auto &[variantIndex, variantName] : assetExtended.asset .materialVariants | ranges::views::enumerate) {
1018
+ if (ImGui::RadioButton (variantName.c_str (), &selected, variantIndex)) {
1019
+ // Apply material variants.
1020
+ for (fastgltf::Mesh &mesh : assetExtended.asset .meshes ) {
1021
+ for (fastgltf::Primitive &primitive : mesh.primitives ) {
1022
+ if (primitive.mappings .empty ()) {
1023
+ // Primitive is not affected by KHR_materials_variants.
1024
+ continue ;
1025
+ }
1026
+
1027
+ if (const auto &variantMaterialIndex = primitive.mappings .at (variantIndex)) {
1028
+ primitive.materialIndex .emplace (*variantMaterialIndex);
1029
+ }
1030
+ else {
1031
+ const auto &originalMaterialIndex = assetExtended.originalMaterialIndexByPrimitive .at (&primitive);
1032
+ primitive.materialIndex .emplace (originalMaterialIndex.value ());
1033
+ }
1034
+
1035
+ tasks.emplace (std::in_place_type<task::PrimitiveMaterialChanged>, &primitive);
1036
+ }
1037
+ }
1018
1038
assetExtended.imGuiSelectedMaterialVariantsIndex .emplace (selected);
1019
- tasks.emplace (std::in_place_type<task::SelectMaterialVariants>, i);
1020
1039
}
1021
1040
}
1022
1041
}
@@ -1406,20 +1425,69 @@ void vk_gltf_viewer::control::ImGuiTaskCollector::nodeInspector(gltf::AssetExten
1406
1425
for (auto &&[primitiveIndex, primitive]: mesh.primitives | ranges::views::enumerate) {
1407
1426
if (ImGui::CollapsingHeader (tempStringBuffer.write (" Primitive {}" , primitiveIndex).view ().c_str ())) {
1408
1427
ImGui::LabelText (" Type" , " %s" , to_string (primitive.type ).c_str ());
1428
+
1429
+ bool primitiveMaterialChanged = false ;
1430
+
1431
+ const char * previewValue = " -" ;
1409
1432
if (primitive.materialIndex ) {
1410
- ImGui::WithID (*primitive.materialIndex , [&]() {
1411
- ImGui::WithLabel (" Material" sv, [&]() {
1412
- if (ImGui::TextLink (getDisplayName (assetExtended.asset , assetExtended.asset .materials [*primitive.materialIndex ]).c_str ())) {
1413
- makeWindowVisible (" Material Editor" );
1414
- assetExtended.imGuiSelectedMaterialIndex .emplace (*primitive.materialIndex );
1415
- }
1433
+ previewValue = getDisplayName (assetExtended.asset , assetExtended.asset .materials [*primitive.materialIndex ]).c_str ();
1434
+ }
1435
+
1436
+ if (ImGui::BeginCombo (" Material" , previewValue)) {
1437
+ if (ImGui::Selectable (" -" , !primitive.materialIndex ) && primitive.materialIndex ) {
1438
+ // Unassign material.
1439
+ primitive.materialIndex .reset ();
1440
+ primitiveMaterialChanged = true ;
1441
+ }
1442
+
1443
+ for (const auto &[materialIndex, material] : assetExtended.asset .materials | ranges::views::enumerate) {
1444
+ ImGui::WithID (materialIndex, [&] {
1445
+ ImGui::WithDisabled ([&] {
1446
+ if (ImGui::Selectable (getDisplayName (assetExtended.asset , material).c_str (), primitive.materialIndex == materialIndex) &&
1447
+ primitive.materialIndex != materialIndex) {
1448
+ primitive.materialIndex .emplace (materialIndex);
1449
+ primitiveMaterialChanged = true ;
1450
+ }
1451
+ }, !gltf::isMaterialCompatible (material, primitive));
1416
1452
});
1417
- });
1453
+ }
1454
+
1455
+ ImGui::EndCombo ();
1418
1456
}
1419
- else {
1420
- ImGui::WithDisabled ([]() {
1421
- ImGui::LabelText (" Material" , " -" );
1422
- });
1457
+
1458
+ const auto &originalMaterialIndex = assetExtended.originalMaterialIndexByPrimitive .at (&primitive);
1459
+ if (to_optional (primitive.materialIndex ) != originalMaterialIndex) {
1460
+ ImGui::SameLine ();
1461
+ if (ImGui::SmallButton (" Reset" )) {
1462
+ if (originalMaterialIndex) {
1463
+ primitive.materialIndex .emplace (*originalMaterialIndex);
1464
+ }
1465
+ else {
1466
+ primitive.materialIndex .reset ();
1467
+ }
1468
+ primitiveMaterialChanged = true ;
1469
+ }
1470
+ }
1471
+
1472
+ if (primitiveMaterialChanged) {
1473
+ if (!primitive.mappings .empty ()) {
1474
+ // If primitive is affected by KHR_materials_variants, current active material variant
1475
+ // index needed to be recalculated.
1476
+ assetExtended.imGuiSelectedMaterialVariantsIndex = gltf::getActiveMaterialVariantIndex (
1477
+ assetExtended.asset ,
1478
+ [&](const fastgltf::Primitive &primitive) {
1479
+ return assetExtended.originalMaterialIndexByPrimitive .at (&primitive);
1480
+ });
1481
+ }
1482
+
1483
+ // Assign assetExtended.imGuiSelectedMaterialIndex as primitive material index (maybe nullopt).
1484
+ if ((assetExtended.imGuiSelectedMaterialIndex = primitive.materialIndex )) {
1485
+ // If assigned material is not nullopt, open the material editor.
1486
+ // It will show the assigned material.
1487
+ makeWindowVisible (" Material Editor" );
1488
+ }
1489
+
1490
+ tasks.emplace (std::in_place_type<task::PrimitiveMaterialChanged>, &primitive);
1423
1491
}
1424
1492
1425
1493
attributeTable (
0 commit comments