From ce2f6c1306ee16bc8eb1c89e7c4a3efc6ee83a0b Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Sun, 26 Apr 2026 14:28:54 +0300 Subject: [PATCH] Navmesh generation works with cell grids --- .../components/ProceduralMaterialModule.cpp | 7 + .../editScene/recast/TileCacheNavMesh.cpp | 11 +- .../editScene/systems/CellGridSystem.cpp | 14 + .../editScene/systems/NavMeshSystem.cpp | 15 +- .../systems/ProceduralMaterialSystem.cpp | 49 ++- .../editScene/ui/ProceduralTextureEditor.cpp | 288 +++++++++++------- 6 files changed, 241 insertions(+), 143 deletions(-) diff --git a/src/features/editScene/components/ProceduralMaterialModule.cpp b/src/features/editScene/components/ProceduralMaterialModule.cpp index 3e594f2..5c5eb9c 100644 --- a/src/features/editScene/components/ProceduralMaterialModule.cpp +++ b/src/features/editScene/components/ProceduralMaterialModule.cpp @@ -2,6 +2,7 @@ #include "../ui/ComponentRegistration.hpp" #include "../ui/ProceduralMaterialEditor.hpp" #include +#include // Register ProceduralMaterial component REGISTER_COMPONENT_GROUP("Procedural Material", "Material", ProceduralMaterialComponent, ProceduralMaterialEditor) @@ -22,6 +23,12 @@ REGISTER_COMPONENT_GROUP("Procedural Material", "Material", ProceduralMaterialCo // Clean up Ogre material - wrap in try/catch since MaterialManager may be shutting down if (material.ogreMaterial) { try { + Ogre::RTShader::ShaderGenerator *shaderGen = + Ogre::RTShader::ShaderGenerator::getSingletonPtr(); + if (shaderGen) { + shaderGen->removeAllShaderBasedTechniques( + *material.ogreMaterial); + } if (Ogre::MaterialManager::getSingletonPtr()) { Ogre::MaterialManager::getSingleton().remove(material.ogreMaterial); } diff --git a/src/features/editScene/recast/TileCacheNavMesh.cpp b/src/features/editScene/recast/TileCacheNavMesh.cpp index 9c9d4b3..7549c1c 100644 --- a/src/features/editScene/recast/TileCacheNavMesh.cpp +++ b/src/features/editScene/recast/TileCacheNavMesh.cpp @@ -18,9 +18,14 @@ static bool isNavMeshGeometry(const Ogre::String &meshName) Ogre::String lower = meshName; std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c) { return std::tolower(c); }); - static const char *exclude[] = { "wall", "ceiling", "roof", - "door", "window", "frame", - "furniture" }; + + // Exclude geometry that doesn't affect floor-level navigation. + // Ceilings are above walkable floors and don't block movement. + // Furniture is handled separately (or excluded to keep navmesh + // focused on architectural walkable surfaces). + // Frames placed via StaticGeometry aren't traversed by the + // SceneNode walker anyway. + static const char *exclude[] = { "ceiling", "frame", "furniture" }; for (const char *pat : exclude) { if (lower.find(pat) != Ogre::String::npos) return false; diff --git a/src/features/editScene/systems/CellGridSystem.cpp b/src/features/editScene/systems/CellGridSystem.cpp index 6f049f0..eca00a0 100644 --- a/src/features/editScene/systems/CellGridSystem.cpp +++ b/src/features/editScene/systems/CellGridSystem.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -2639,6 +2640,19 @@ void CellGridSystem::updateTownMaterial(flecs::entity townEntity) pass->setAmbient(Ogre::ColourValue(0.4f, 0.4f, 0.4f)); pass->setSpecular(Ogre::ColourValue(0.1f, 0.1f, 0.1f)); + // Register with RTSS so the material works on shader-only render systems + Ogre::RTShader::ShaderGenerator *shaderGen = + Ogre::RTShader::ShaderGenerator::getSingletonPtr(); + if (shaderGen) { + shaderGen->createShaderBasedTechnique( + *mat, + Ogre::MaterialManager::DEFAULT_SCHEME_NAME, + Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME); + shaderGen->validateMaterial( + Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, + town.materialName); + } + Ogre::LogManager::getSingleton().logMessage( "CellGrid: Updated town material '" + town.materialName + "'"); } diff --git a/src/features/editScene/systems/NavMeshSystem.cpp b/src/features/editScene/systems/NavMeshSystem.cpp index f765737..24ab479 100644 --- a/src/features/editScene/systems/NavMeshSystem.cpp +++ b/src/features/editScene/systems/NavMeshSystem.cpp @@ -19,14 +19,13 @@ static bool isNavMeshGeometry(const Ogre::String &meshName) std::transform(lower.begin(), lower.end(), lower.begin(), [](unsigned char c) { return std::tolower(c); }); - // Exclude vertical / enclosing geometry that causes Recast - // span-merging artefacts. When a floor span merges with a wall - // span the walkable surface is pushed to the top of the wall; - // if a roof is close above, rcFilterWalkableLowHeightSpans - // removes the whole column. - static const char *exclude[] = { "wall", "ceiling", "roof", - "door", "window", "frame", - "furniture" }; + // Exclude geometry that doesn't affect floor-level navigation. + // Ceilings are above walkable floors and don't block movement. + // Furniture is handled separately (or excluded to keep navmesh + // focused on architectural walkable surfaces). + // Frames placed via StaticGeometry aren't traversed by the + // SceneNode walker anyway. + static const char *exclude[] = { "ceiling", "frame", "furniture" }; for (const char *pat : exclude) { if (lower.find(pat) != Ogre::String::npos) return false; diff --git a/src/features/editScene/systems/ProceduralMaterialSystem.cpp b/src/features/editScene/systems/ProceduralMaterialSystem.cpp index 8a2e32d..e375b37 100644 --- a/src/features/editScene/systems/ProceduralMaterialSystem.cpp +++ b/src/features/editScene/systems/ProceduralMaterialSystem.cpp @@ -67,22 +67,32 @@ void ProceduralMaterialSystem::createMaterial( "_" + std::to_string(m_createdCount++); } - // Destroy old material if exists - if (component.ogreMaterial) { - destroyMaterial(component); + Ogre::MaterialManager &matMgr = + Ogre::MaterialManager::getSingleton(); + + // Re-use the existing material object when possible. + // Destroying and recreating breaks cached MaterialPtr + // references held by Ogre::SubEntity instances that use + // this material. + if (!component.ogreMaterial) { + if (matMgr.resourceExists(component.materialName)) { + component.ogreMaterial = + matMgr.getByName(component.materialName); + } else { + component.ogreMaterial = matMgr.create( + component.materialName, + Ogre::ResourceGroupManager:: + DEFAULT_RESOURCE_GROUP_NAME); + } } - // Create new material - component.ogreMaterial = - Ogre::MaterialManager::getSingleton().create( - component.materialName, - Ogre::ResourceGroupManager:: - DEFAULT_RESOURCE_GROUP_NAME); - - // Get the default technique and pass + // Clear existing technique and rebuild passes so that every + // SubEntity::mMaterialPtr (which points to this same object) + // sees the updated state. Ogre::Technique *technique = component.ogreMaterial->getTechnique(0); - Ogre::Pass *pass = technique->getPass(0); + technique->removeAllPasses(); + Ogre::Pass *pass = technique->createPass(); // Set material colors pass->setAmbient(component.ambient[0], component.ambient[1], @@ -116,10 +126,12 @@ void ProceduralMaterialSystem::createMaterial( } } - // Register with RTSS to generate shaders (fixes "RenderSystem does not support FixedFunction") + // Re-generate RTSS shaders for the updated material Ogre::RTShader::ShaderGenerator *shaderGen = Ogre::RTShader::ShaderGenerator::getSingletonPtr(); if (shaderGen && component.ogreMaterial) { + shaderGen->removeAllShaderBasedTechniques( + *component.ogreMaterial); shaderGen->createShaderBasedTechnique( *component.ogreMaterial, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, @@ -136,7 +148,7 @@ void ProceduralMaterialSystem::createMaterial( component.textureVersion = currentTexVersion; Ogre::LogManager::getSingleton().logMessage( - "ProceduralMaterial: Created '" + + "ProceduralMaterial: Updated '" + component.materialName + "'"); } catch (const Ogre::Exception &e) { @@ -151,6 +163,15 @@ void ProceduralMaterialSystem::destroyMaterial( { if (component.ogreMaterial) { try { + // Remove RTSS shader techniques before destroying the + // material, otherwise the shader generator keeps stale + // cache entries keyed by material name. + Ogre::RTShader::ShaderGenerator *shaderGen = + Ogre::RTShader::ShaderGenerator::getSingletonPtr(); + if (shaderGen) { + shaderGen->removeAllShaderBasedTechniques( + *component.ogreMaterial); + } Ogre::MaterialManager::getSingleton().remove( component.ogreMaterial); } catch (...) { diff --git a/src/features/editScene/ui/ProceduralTextureEditor.cpp b/src/features/editScene/ui/ProceduralTextureEditor.cpp index 43c1ea1..73ac38d 100644 --- a/src/features/editScene/ui/ProceduralTextureEditor.cpp +++ b/src/features/editScene/ui/ProceduralTextureEditor.cpp @@ -6,128 +6,147 @@ #include #include -void ProceduralTextureEditor::renderColorButton(int index, ProceduralTextureComponent &texture) +void ProceduralTextureEditor::renderColorButton( + int index, ProceduralTextureComponent &texture) { Ogre::ColourValue color = texture.getColor(index); - + // Create a unique ID for this button ImGui::PushID(index); - + // Show color as a small colored button ImVec4 buttonColor(color.r, color.g, color.b, color.a); - ImGui::ColorButton("##color", buttonColor, ImGuiColorEditFlags_NoTooltip, ImVec2(24, 24)); - + ImGui::ColorButton("##color", buttonColor, + ImGuiColorEditFlags_NoTooltip, ImVec2(24, 24)); + // Handle click if (ImGui::IsItemClicked()) { m_selectedRect = index; } - + // Show tooltip with rectangle index if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Rect %d: (%.2f, %.2f, %.2f)", index, color.r, color.g, color.b); + ImGui::SetTooltip("Rect %d: (%.2f, %.2f, %.2f)", index, color.r, + color.g, color.b); } - + ImGui::PopID(); } -void ProceduralTextureEditor::renderColorGrid(flecs::entity entity, ProceduralTextureComponent &texture) +void ProceduralTextureEditor::renderColorGrid( + flecs::entity entity, ProceduralTextureComponent &texture) { const int gridSize = ProceduralTextureComponent::GRID_SIZE; - - ImGui::Text("10x10 Grid - Click a rectangle to edit its color or add to atlas:"); - + + ImGui::Text( + "10x10 Grid - Click a rectangle to edit its color or add to atlas:"); + // Calculate grid width for centering float buttonSize = 24.0f; float spacing = 2.0f; float gridWidth = gridSize * buttonSize + (gridSize - 1) * spacing; - + // Get window width for centering float windowWidth = ImGui::GetContentRegionAvail().x; float startX = ImGui::GetCursorPosX(); float offset = (windowWidth - gridWidth) * 0.5f; - if (offset < 0) offset = 0; - + if (offset < 0) + offset = 0; + // Render the grid - each row needs its own offset for (int row = 0; row < gridSize; ++row) { // Set cursor position for this row ImGui::SetCursorPosX(startX + offset); - + for (int col = 0; col < gridSize; ++col) { int index = row * gridSize + col; renderColorButton(index, texture); - + if (col < gridSize - 1) { ImGui::SameLine(0, spacing); } } } - + // Color picker and naming for selected rectangle - if (m_selectedRect >= 0 && m_selectedRect < ProceduralTextureComponent::RECT_COUNT) { + if (m_selectedRect >= 0 && + m_selectedRect < ProceduralTextureComponent::RECT_COUNT) { ImGui::Separator(); - ImGui::Text("Editing Rectangle %d (Row %d, Col %d)", - m_selectedRect, - m_selectedRect / gridSize, - m_selectedRect % gridSize); - + ImGui::Text("Editing Rectangle %d (Row %d, Col %d)", + m_selectedRect, m_selectedRect / gridSize, + m_selectedRect % gridSize); + // UV coordinates display float u1, v1, u2, v2; texture.getRectUVs(m_selectedRect, u1, v1, u2, v2); - ImGui::TextDisabled("UVs: (%.3f, %.3f) - (%.3f, %.3f)", u1, v1, u2, v2); - - Ogre::ColourValue currentColor = texture.getColor(m_selectedRect); - float colorArray[4] = { currentColor.r, currentColor.g, currentColor.b, currentColor.a }; - + ImGui::TextDisabled("UVs: (%.3f, %.3f) - (%.3f, %.3f)", u1, v1, + u2, v2); + + Ogre::ColourValue currentColor = + texture.getColor(m_selectedRect); + float colorArray[4] = { currentColor.r, currentColor.g, + currentColor.b, currentColor.a }; + if (ImGui::ColorEdit4("Color", colorArray)) { - Ogre::ColourValue newColor(colorArray[0], colorArray[1], colorArray[2], colorArray[3]); + Ogre::ColourValue newColor(colorArray[0], colorArray[1], + colorArray[2], + colorArray[3]); texture.setColor(m_selectedRect, newColor); } - + // Add to atlas section ImGui::Separator(); ImGui::Text("Add to Texture Atlas:"); - + ImGui::InputText("Name", m_nameBuffer, sizeof(m_nameBuffer)); ImGui::SameLine(); - + if (ImGui::Button("Add")) { if (strlen(m_nameBuffer) > 0) { if (texture.hasNamedRect(m_nameBuffer)) { - ImGui::TextColored(ImVec4(1, 0, 0, 1), "Name already exists!"); + ImGui::TextColored( + ImVec4(1, 0, 0, 1), + "Name already exists!"); } else { - texture.addNamedRect(m_nameBuffer, m_selectedRect); - m_nameBuffer[0] = '\0'; // Clear buffer + texture.addNamedRect(m_nameBuffer, + m_selectedRect); + m_nameBuffer[0] = '\0'; // Clear buffer } } } - + if (ImGui::Button("Deselect")) { m_selectedRect = -1; m_nameBuffer[0] = '\0'; } - + ImGui::SameLine(); - + // Preset colors ImGui::Text("Presets:"); ImGui::SameLine(); - + const ImVec4 presets[] = { - ImVec4(1, 1, 1, 1), // White - ImVec4(0, 0, 0, 1), // Black - ImVec4(1, 0, 0, 1), // Red - ImVec4(0, 1, 0, 1), // Green - ImVec4(0, 0, 1, 1), // Blue - ImVec4(1, 1, 0, 1), // Yellow - ImVec4(1, 0, 1, 1), // Magenta - ImVec4(0, 1, 1, 1), // Cyan - ImVec4(0.5f, 0.5f, 0.5f, 1), // Gray + ImVec4(1, 1, 1, 1), // White + ImVec4(0, 0, 0, 1), // Black + ImVec4(1, 0, 0, 1), // Red + ImVec4(0, 1, 0, 1), // Green + ImVec4(0, 0, 1, 1), // Blue + ImVec4(1, 1, 0, 1), // Yellow + ImVec4(1, 0, 1, 1), // Magenta + ImVec4(0, 1, 1, 1), // Cyan + ImVec4(0.5f, 0.5f, 0.5f, 1), // Gray }; - + for (size_t i = 0; i < IM_ARRAYSIZE(presets); ++i) { ImGui::PushID((int)i); - if (ImGui::ColorButton("##preset", presets[i], ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20))) { - Ogre::ColourValue presetColor(presets[i].x, presets[i].y, presets[i].z, presets[i].w); + if (ImGui::ColorButton("##preset", presets[i], + ImGuiColorEditFlags_NoTooltip, + ImVec2(20, 20))) { + Ogre::ColourValue presetColor(presets[i].x, + presets[i].y, + presets[i].z, + presets[i].w); texture.setColor(m_selectedRect, presetColor); } ImGui::PopID(); @@ -138,35 +157,40 @@ void ProceduralTextureEditor::renderColorGrid(flecs::entity entity, ProceduralTe } } -void ProceduralTextureEditor::renderNamedRects(flecs::entity entity, ProceduralTextureComponent &texture) +void ProceduralTextureEditor::renderNamedRects( + flecs::entity entity, ProceduralTextureComponent &texture) { ImGui::Separator(); ImGui::Text("Texture Atlas (Named Rectangles):"); - - const auto& namedRects = texture.getAllNamedRects(); - + + const auto &namedRects = texture.getAllNamedRects(); + if (namedRects.empty()) { - ImGui::TextDisabled("No named rectangles. Select a rectangle above and add it to the atlas."); + ImGui::TextDisabled( + "No named rectangles. Select a rectangle above and add it to the atlas."); } else { // Table header - if (ImGui::BeginTable("NamedRects", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (ImGui::BeginTable("NamedRects", 3, + ImGuiTableFlags_Borders | + ImGuiTableFlags_RowBg)) { ImGui::TableSetupColumn("Name"); ImGui::TableSetupColumn("UV Coordinates"); ImGui::TableSetupColumn("Action"); ImGui::TableHeadersRow(); - - for (const auto& pair : namedRects) { - const auto& rect = pair.second; + + for (const auto &pair : namedRects) { + const auto &rect = pair.second; ImGui::TableNextRow(); - + // Name column ImGui::TableNextColumn(); ImGui::Text("%s", rect.name.c_str()); - + // UVs column ImGui::TableNextColumn(); - ImGui::Text("(%.3f, %.3f) - (%.3f, %.3f)", rect.u1, rect.v1, rect.u2, rect.v2); - + ImGui::Text("(%.3f, %.3f) - (%.3f, %.3f)", + rect.u1, rect.v1, rect.u2, rect.v2); + // Action column ImGui::TableNextColumn(); ImGui::PushID(rect.name.c_str()); @@ -175,49 +199,62 @@ void ProceduralTextureEditor::renderNamedRects(flecs::entity entity, ProceduralT } ImGui::PopID(); } - + ImGui::EndTable(); } - - ImGui::TextDisabled("Total: %zu named rectangles", namedRects.size()); + + ImGui::TextDisabled("Total: %zu named rectangles", + namedRects.size()); } } -bool ProceduralTextureEditor::renderComponent(flecs::entity entity, ProceduralTextureComponent &texture) +bool ProceduralTextureEditor::renderComponent( + flecs::entity entity, ProceduralTextureComponent &texture) { bool modified = false; - - if (ImGui::CollapsingHeader("Procedural Texture", ImGuiTreeNodeFlags_DefaultOpen)) { + + if (ImGui::CollapsingHeader("Procedural Texture", + ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Indent(); - + // Texture info if (texture.generated) { - ImGui::TextColored(ImVec4(0, 1, 0, 1), "Status: Generated"); + ImGui::TextColored(ImVec4(0, 1, 0, 1), + "Status: Generated"); ImGui::Text("Texture: %s", texture.textureName.c_str()); - ImGui::Text("Size: %dx%d", texture.textureSize, texture.textureSize); - + ImGui::Text("Size: %dx%d", texture.textureSize, + texture.textureSize); + // Save PNG button if (ImGui::Button("Save as PNG...")) { ImGui::OpenPopup("SaveTexturePopup"); } - + // Save popup if (ImGui::BeginPopup("SaveTexturePopup")) { - static char filename[256] = "procedural_texture.png"; - ImGui::InputText("Filename", filename, sizeof(filename)); - + static char filename[256] = + "procedural_texture.png"; + ImGui::InputText("Filename", filename, + sizeof(filename)); + if (ImGui::Button("Save", ImVec2(120, 0))) { try { if (texture.ogreTexture) { Ogre::Image image; - texture.ogreTexture->convertToImage(image); + texture.ogreTexture + ->convertToImage( + image); image.save(filename); - Ogre::LogManager::getSingleton().logMessage( - "ProceduralTexture: Saved to " + std::string(filename)); + Ogre::LogManager::getSingleton() + .logMessage( + "ProceduralTexture: Saved to " + + std::string( + filename)); } - } catch (const Ogre::Exception& e) { + } catch (const Ogre::Exception &e) { Ogre::LogManager::getSingleton().logMessage( - "ProceduralTexture ERROR: Failed to save: " + e.getDescription()); + "ProceduralTexture ERROR: Failed to save: " + + e.getDescription()); } ImGui::CloseCurrentPopup(); } @@ -228,91 +265,106 @@ bool ProceduralTextureEditor::renderComponent(flecs::entity entity, ProceduralTe ImGui::EndPopup(); } } else if (texture.dirty) { - ImGui::TextColored(ImVec4(1, 1, 0, 1), "Status: Needs Generation"); + ImGui::TextColored(ImVec4(1, 1, 0, 1), + "Status: Needs Generation"); } else { - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1), "Status: Not Generated"); + ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1), + "Status: Not Generated"); } - + ImGui::Separator(); - + // Texture size selector const int sizes[] = { 128, 256, 512, 1024, 2048 }; - int currentSizeIndex = 2; // Default 512 + int currentSizeIndex = 2; // Default 512 for (int i = 0; i < IM_ARRAYSIZE(sizes); ++i) { if (sizes[i] == texture.textureSize) { currentSizeIndex = i; break; } } - - const char* sizeNames[] = { "128x128", "256x256", "512x512", "1024x1024", "2048x2048" }; - if (ImGui::Combo("Texture Size", ¤tSizeIndex, sizeNames, IM_ARRAYSIZE(sizeNames))) { + + const char *sizeNames[] = { "128x128", "256x256", "512x512", + "1024x1024", "2048x2048" }; + if (ImGui::Combo("Texture Size", ¤tSizeIndex, sizeNames, + IM_ARRAYSIZE(sizeNames))) { texture.textureSize = sizes[currentSizeIndex]; texture.markDirty(); modified = true; } - + // UV Margin control to prevent color bleeding ImGui::Separator(); ImGui::Text("UV Margin (prevents color bleeding):"); - if (ImGui::DragFloat("Margin", &texture.uvMargin, 0.001f, 0.01f, 0.025f, "%.3f")) { + if (ImGui::DragFloat("Margin", &texture.uvMargin, 0.001f, 0.01f, + 0.035f, "%.3f")) { // Clamp to valid range - if (texture.uvMargin < 0.01f) texture.uvMargin = 0.01f; - if (texture.uvMargin > 0.025f) texture.uvMargin = 0.025f; + if (texture.uvMargin < 0.01f) + texture.uvMargin = 0.01f; + if (texture.uvMargin > 0.035f) + texture.uvMargin = 0.035f; texture.markDirty(); modified = true; } - ImGui::TextDisabled("Default: 0.010, Range: 0.010-0.025, Step: 0.001"); - ImGui::TextDisabled("Higher values = more padding, less color bleeding"); - + ImGui::TextDisabled( + "Default: 0.010, Range: 0.010-0.035, Step: 0.001"); + ImGui::TextDisabled( + "Higher values = more padding, less color bleeding"); + ImGui::Separator(); - + // Color grid renderColorGrid(entity, texture); - + // Named rectangles list renderNamedRects(entity, texture); - + ImGui::Separator(); - + // Global actions if (ImGui::Button("Randomize Colors")) { - for (int i = 0; i < ProceduralTextureComponent::RECT_COUNT; ++i) { + for (int i = 0; + i < ProceduralTextureComponent::RECT_COUNT; ++i) { Ogre::ColourValue randomColor( (float)rand() / RAND_MAX, (float)rand() / RAND_MAX, - (float)rand() / RAND_MAX, - 1.0f - ); + (float)rand() / RAND_MAX, 1.0f); texture.setColor(i, randomColor); } modified = true; } - + ImGui::SameLine(); - + if (ImGui::Button("Reset to Checkerboard")) { - for (int i = 0; i < ProceduralTextureComponent::RECT_COUNT; ++i) { - int row = i / ProceduralTextureComponent::GRID_SIZE; - int col = i % ProceduralTextureComponent::GRID_SIZE; + for (int i = 0; + i < ProceduralTextureComponent::RECT_COUNT; ++i) { + int row = i / + ProceduralTextureComponent::GRID_SIZE; + int col = i % + ProceduralTextureComponent::GRID_SIZE; bool isWhite = (row + col) % 2 == 0; - Ogre::ColourValue color(isWhite ? 1.0f : 0.0f, isWhite ? 1.0f : 0.0f, isWhite ? 1.0f : 0.0f, 1.0f); + Ogre::ColourValue color(isWhite ? 1.0f : 0.0f, + isWhite ? 1.0f : 0.0f, + isWhite ? 1.0f : 0.0f, + 1.0f); texture.setColor(i, color); } modified = true; } - + ImGui::SameLine(); - + if (ImGui::Button("All White")) { - for (int i = 0; i < ProceduralTextureComponent::RECT_COUNT; ++i) { + for (int i = 0; + i < ProceduralTextureComponent::RECT_COUNT; ++i) { texture.setColor(i, Ogre::ColourValue::White); } modified = true; } - + ImGui::Unindent(); } - + return modified; }