Compare commits

..

2 Commits

Author SHA1 Message Date
d8122e3275 Fixed floor offset 2026-04-06 02:16:45 +03:00
0ebba40867 Corners finally match 2026-04-06 01:45:26 +03:00
6 changed files with 1996 additions and 951 deletions

View File

@@ -119,6 +119,15 @@ struct CellGridComponent {
// Generation script (Lua or custom format)
std::string generationScript;
// Texture rectangle names for different parts (from ProceduralTexture)
std::string floorRectName;
std::string ceilingRectName;
std::string extWallRectName;
std::string intWallRectName;
std::string doorRectName;
std::string windowRectName;
std::string roofRectName;
// Dirty flag - triggers rebuild
bool dirty = true;
unsigned int version = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,7 @@ private:
void buildDoors(const struct CellGridComponent& grid, std::vector<Procedural::TriangleBuffer>& doorTbs);
void buildWindows(const struct CellGridComponent& grid, std::vector<Procedural::TriangleBuffer>& windowTbs);
void buildCorners(const struct CellGridComponent& grid, Procedural::TriangleBuffer& extWallTb);
void buildInternalCorners(const struct CellGridComponent& grid, Procedural::TriangleBuffer& intWallTb);
// Build roofs
void buildRoofs(flecs::entity lotEntity, const struct CellGridComponent& grid, Procedural::TriangleBuffer& roofTb);
@@ -60,7 +61,10 @@ private:
Ogre::MeshPtr convertToMesh(const std::string& name, Procedural::TriangleBuffer& tb, const std::string& materialName);
// Apply UV mapping from color rects
void applyUVMapping(Procedural::TriangleBuffer& tb, const struct TownComponent& town, const std::string& rectName);
void applyUVMapping(Procedural::TriangleBuffer& tb, flecs::entity entity, const std::string& rectName);
// Apply UV mapping using texture coordinates directly
void applyUVMappingToBuffer(Procedural::TriangleBuffer& tb, const std::string& rectName, flecs::entity materialEntity);
// Destroy existing mesh
void destroyCellGridMeshes(struct CellGridComponent& grid);

View File

@@ -1269,6 +1269,15 @@ nlohmann::json SceneSerializer::serializeCellGrid(flecs::entity entity)
json["cellHeight"] = grid.cellHeight;
json["generationScript"] = grid.generationScript;
// Serialize texture rectangles
json["floorRectName"] = grid.floorRectName;
json["ceilingRectName"] = grid.ceilingRectName;
json["extWallRectName"] = grid.extWallRectName;
json["intWallRectName"] = grid.intWallRectName;
json["doorRectName"] = grid.doorRectName;
json["windowRectName"] = grid.windowRectName;
json["roofRectName"] = grid.roofRectName;
// Serialize cells
nlohmann::json cellsJson = nlohmann::json::array();
for (const auto& cell : grid.cells) {
@@ -1433,6 +1442,15 @@ void SceneSerializer::deserializeCellGrid(flecs::entity entity, const nlohmann::
grid.cellHeight = json.value("cellHeight", 4.0f);
grid.generationScript = json.value("generationScript", "");
// Deserialize texture rectangles
grid.floorRectName = json.value("floorRectName", "");
grid.ceilingRectName = json.value("ceilingRectName", "");
grid.extWallRectName = json.value("extWallRectName", "");
grid.intWallRectName = json.value("intWallRectName", "");
grid.doorRectName = json.value("doorRectName", "");
grid.windowRectName = json.value("windowRectName", "");
grid.roofRectName = json.value("roofRectName", "");
// Deserialize cells
if (json.contains("cells") && json["cells"].is_array()) {
for (const auto& cellJson : json["cells"]) {

View File

@@ -1,5 +1,7 @@
#include "CellGridEditor.hpp"
#include "../components/CellGrid.hpp"
#include "../components/ProceduralMaterial.hpp"
#include "../components/ProceduralTexture.hpp"
#include <OgreStringConverter.h>
bool CellGridEditor::renderComponent(flecs::entity entity, CellGridComponent& grid)
@@ -42,6 +44,11 @@ bool CellGridEditor::renderComponent(flecs::entity entity, CellGridComponent& gr
renderFurnitureEditor(grid);
}
// Texture rectangle editor
if (ImGui::CollapsingHeader("Texture Rectangles")) {
renderTextureRectEditor(entity, grid);
}
// Script editor
if (ImGui::CollapsingHeader("Generation Script")) {
renderScriptEditor(grid);
@@ -91,6 +98,7 @@ void CellGridEditor::renderCellEditor(CellGridComponent& grid)
auto flags = CellGridComponent::getAllFlags();
for (const auto& [flag, name] : flags) {
ImGui::PushID((int)flag);
bool hasFlag = cell->hasFlag(flag);
if (ImGui::Checkbox(name, &hasFlag)) {
if (hasFlag) {
@@ -100,6 +108,7 @@ void CellGridEditor::renderCellEditor(CellGridComponent& grid)
}
grid.markDirty();
}
ImGui::PopID();
}
if (ImGui::Button("Delete Cell")) {
@@ -223,3 +232,123 @@ void CellGridEditor::renderScriptEditor(CellGridComponent& grid)
grid.markDirty();
}
}
void CellGridEditor::renderTextureRectEditor(flecs::entity entity, CellGridComponent& grid)
{
// Find available texture rectangles from parent material
flecs::entity textureEntity = flecs::entity::null();
flecs::entity parent = entity.parent();
while (parent.is_alive()) {
if (parent.has<LotComponent>()) {
auto& lot = parent.get<LotComponent>();
if (lot.proceduralMaterialEntity.is_alive() &&
lot.proceduralMaterialEntity.has<ProceduralMaterialComponent>()) {
const auto& mat = lot.proceduralMaterialEntity.get<ProceduralMaterialComponent>();
if (mat.diffuseTextureEntity.is_alive()) {
textureEntity = mat.diffuseTextureEntity;
break;
}
}
}
if (parent.has<DistrictComponent>()) {
auto& district = parent.get<DistrictComponent>();
if (district.proceduralMaterialEntity.is_alive() &&
district.proceduralMaterialEntity.has<ProceduralMaterialComponent>()) {
const auto& mat = district.proceduralMaterialEntity.get<ProceduralMaterialComponent>();
if (mat.diffuseTextureEntity.is_alive()) {
textureEntity = mat.diffuseTextureEntity;
break;
}
}
}
if (parent.has<TownComponent>()) {
auto& town = parent.get<TownComponent>();
if (town.proceduralMaterialEntity.is_alive() &&
town.proceduralMaterialEntity.has<ProceduralMaterialComponent>()) {
const auto& mat = town.proceduralMaterialEntity.get<ProceduralMaterialComponent>();
if (mat.diffuseTextureEntity.is_alive()) {
textureEntity = mat.diffuseTextureEntity;
break;
}
}
break;
}
parent = parent.parent();
}
if (!textureEntity.is_alive() || !textureEntity.has<ProceduralTextureComponent>()) {
ImGui::TextDisabled("No ProceduralMaterial with texture found in parent hierarchy");
return;
}
const auto& texture = textureEntity.get<ProceduralTextureComponent>();
const auto& namedRects = texture.getAllNamedRects();
if (namedRects.empty()) {
ImGui::TextDisabled("No named rectangles defined in texture");
return;
}
// Build list of rect names
std::vector<std::string> rectNames;
rectNames.push_back("(default)");
for (const auto& pair : namedRects) {
rectNames.push_back(pair.first);
}
auto renderRectCombo = [&](const char* label, std::string& currentValue) {
int currentIndex = 0;
for (size_t i = 1; i < rectNames.size(); ++i) {
if (currentValue == rectNames[i]) {
currentIndex = (int)i;
break;
}
}
std::string comboItems;
for (size_t i = 0; i < rectNames.size(); ++i) {
if (i > 0) comboItems += '\0';
comboItems += rectNames[i];
}
comboItems += '\0';
int newIndex = currentIndex;
if (ImGui::Combo(label, &newIndex, comboItems.c_str())) {
if (newIndex == 0) {
currentValue.clear();
} else {
currentValue = rectNames[newIndex];
}
return true;
}
return false;
};
ImGui::Text("Select texture rectangles for each part:");
ImGui::Indent();
if (renderRectCombo("Floor", grid.floorRectName)) {
grid.markDirty();
}
if (renderRectCombo("Ceiling", grid.ceilingRectName)) {
grid.markDirty();
}
if (renderRectCombo("External Walls", grid.extWallRectName)) {
grid.markDirty();
}
if (renderRectCombo("Internal Walls", grid.intWallRectName)) {
grid.markDirty();
}
if (renderRectCombo("Doors", grid.doorRectName)) {
grid.markDirty();
}
if (renderRectCombo("Windows", grid.windowRectName)) {
grid.markDirty();
}
if (renderRectCombo("Roof", grid.roofRectName)) {
grid.markDirty();
}
ImGui::Unindent();
}

View File

@@ -13,6 +13,7 @@ private:
void renderCellEditor(CellGridComponent& grid);
void renderFurnitureEditor(CellGridComponent& grid);
void renderScriptEditor(CellGridComponent& grid);
void renderTextureRectEditor(flecs::entity entity, CellGridComponent& grid);
// State for UI
int selectedCellX = 0, selectedCellY = 0, selectedCellZ = 0;