|  | 
|  | 1 | +#include <browedit/BrowEdit.h> | 
|  | 2 | +#include <browedit/Map.h> | 
|  | 3 | +#include <browedit/Node.h> | 
|  | 4 | +#include <browedit/components/Gnd.h> | 
|  | 5 | +#include <browedit/components/Rsw.h> | 
|  | 6 | +#include <glm/gtc/type_ptr.hpp> | 
|  | 7 | +#include <browedit/components/GndRenderer.h> | 
|  | 8 | +#include <browedit/components/GatRenderer.h> | 
|  | 9 | +#include <browedit/components/RsmRenderer.h> | 
|  | 10 | +#include <browedit/components/WaterRenderer.h> | 
|  | 11 | + | 
|  | 12 | +void BrowEdit::showCropSettingsWindow() | 
|  | 13 | +{ | 
|  | 14 | +	if (activeMapView == nullptr) | 
|  | 15 | +		return; | 
|  | 16 | + | 
|  | 17 | +	ImVec2 center = ImGui::GetMainViewport()->GetCenter(); | 
|  | 18 | +	ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); | 
|  | 19 | +	ImGui::Begin("Crop Settings"); | 
|  | 20 | + | 
|  | 21 | +	auto gnd = activeMapView->map->rootNode->getComponent<Gnd>(); | 
|  | 22 | +	auto rsw = activeMapView->map->rootNode->getComponent<Rsw>(); | 
|  | 23 | + | 
|  | 24 | +	if (gnd == nullptr || rsw == nullptr) | 
|  | 25 | +		return; | 
|  | 26 | + | 
|  | 27 | +	auto& settings = rsw->cropSettings; | 
|  | 28 | + | 
|  | 29 | +	std::string info = "Current map size: " + std::to_string(gnd->width) + " / " + std::to_string(gnd->height); | 
|  | 30 | +	ImGui::Text(info.c_str()); | 
|  | 31 | +	ImGui::Checkbox("Height Edit Mode Selection Only", &settings.heightSelectionOnly); | 
|  | 32 | +	ImGui::DragInt("Crop left", &settings.cropLeft, 1, -gnd->width, gnd->width); | 
|  | 33 | +	ImGui::DragInt("Crop right", &settings.cropRight, 1, -gnd->width, gnd->width); | 
|  | 34 | +	ImGui::DragInt("Crop top", &settings.cropTop, 1, -gnd->height, gnd->height); | 
|  | 35 | +	ImGui::DragInt("Crop bottom", &settings.cropBottom, 1, -gnd->height, gnd->height); | 
|  | 36 | +	 | 
|  | 37 | +	if (ImGui::Button("Crop!")) | 
|  | 38 | +	{ | 
|  | 39 | +		auto gat = activeMapView->map->rootNode->getComponent<Gat>(); | 
|  | 40 | +		std::vector<std::vector<Gnd::Cube*>> cubes; | 
|  | 41 | +		std::vector<std::vector<Gat::Cube*>> gatCubes; | 
|  | 42 | +		glm::ivec2 min(gnd->width, gnd->height); | 
|  | 43 | +		glm::ivec2 max(0); | 
|  | 44 | + | 
|  | 45 | +		if (settings.heightSelectionOnly && activeMapView->map->tileSelection.size() == 0) { | 
|  | 46 | +			// Nothing selected! | 
|  | 47 | +		} | 
|  | 48 | +		else { | 
|  | 49 | +			auto gndRenderer = activeMapView->map->rootNode->getComponent<GndRenderer>(); | 
|  | 50 | +			glm::ivec2 oldGndSize(gnd->width, gnd->height); | 
|  | 51 | +			glm::ivec2 oldGatSize(gat->width, gat->height); | 
|  | 52 | + | 
|  | 53 | +			if (settings.heightSelectionOnly) { | 
|  | 54 | +				for (const auto& tile : activeMapView->map->tileSelection) | 
|  | 55 | +				{ //TODO: can this be done with 2 min calls? | 
|  | 56 | +					min.x = glm::min(min.x, tile.x); | 
|  | 57 | +					min.y = glm::min(min.y, tile.y); | 
|  | 58 | +					max.x = glm::max(max.x, tile.x); | 
|  | 59 | +					max.y = glm::max(max.y, tile.y); | 
|  | 60 | +				} | 
|  | 61 | +			} | 
|  | 62 | +			else { | 
|  | 63 | +				min = glm::ivec2(0); | 
|  | 64 | +				max = glm::ivec2(gnd->width - 1, gnd->height - 1); | 
|  | 65 | + | 
|  | 66 | +				min.x += settings.cropLeft; | 
|  | 67 | +				min.y += settings.cropBottom; | 
|  | 68 | +				max.x -= settings.cropRight; | 
|  | 69 | +				max.y -= settings.cropTop; | 
|  | 70 | +			} | 
|  | 71 | + | 
|  | 72 | +			max.x++; | 
|  | 73 | +			max.y++; | 
|  | 74 | + | 
|  | 75 | +			if (min.x < max.x && min.y < max.y) { | 
|  | 76 | +				glm::vec3 cameraOffset(0); | 
|  | 77 | +				glm::vec3 rswObjectOffset(0); | 
|  | 78 | + | 
|  | 79 | +				cameraOffset.x = min.x * 10.0f; | 
|  | 80 | +				cameraOffset.z = (gnd->height - max.y) * 10.0f; | 
|  | 81 | + | 
|  | 82 | +				rswObjectOffset.x = -min.x * 10.0f + 5 * gnd->width; | 
|  | 83 | +				rswObjectOffset.z = (gnd->height - max.y) * 10.0f - 5 * gnd->height; | 
|  | 84 | + | 
|  | 85 | +				gnd->width = max.x - min.x; | 
|  | 86 | +				gnd->height = max.y - min.y; | 
|  | 87 | + | 
|  | 88 | +				rswObjectOffset.x -= 5 * gnd->width; | 
|  | 89 | +				rswObjectOffset.z += 5 * gnd->height; | 
|  | 90 | + | 
|  | 91 | +				for (int x = min.x; x < max.x; x++) | 
|  | 92 | +				{ | 
|  | 93 | +					std::vector<Gnd::Cube*> row; | 
|  | 94 | +					for (int y = min.y; y < max.y; y++) | 
|  | 95 | +					{ | 
|  | 96 | +						if (x < 0 || x >= oldGndSize.x || y < 0 || y >= oldGndSize.y) | 
|  | 97 | +							row.push_back(new Gnd::Cube()); | 
|  | 98 | +						else | 
|  | 99 | +							row.push_back(gnd->cubes[x][y]); | 
|  | 100 | +					} | 
|  | 101 | +					cubes.push_back(row); | 
|  | 102 | +				} | 
|  | 103 | +				for (int x = min.x * 2; x < max.x * 2; x++) | 
|  | 104 | +				{ | 
|  | 105 | +					std::vector<Gat::Cube*> row; | 
|  | 106 | +					for (int y = min.y * 2; y < max.y * 2; y++) | 
|  | 107 | +					{ | 
|  | 108 | +						if (x < 0 || x >= oldGatSize.x || y < 0 || y >= oldGatSize.y) { | 
|  | 109 | +							auto gatCube = new Gat::Cube(); | 
|  | 110 | +							gatCube->gatType = 0; | 
|  | 111 | +							gatCube->normal = glm::vec3(0, -1, 0); | 
|  | 112 | +							row.push_back(gatCube); | 
|  | 113 | +						} | 
|  | 114 | +						else | 
|  | 115 | +							row.push_back(gat->cubes[x][y]); | 
|  | 116 | +					} | 
|  | 117 | + | 
|  | 118 | +					gatCubes.push_back(row); | 
|  | 119 | +				} | 
|  | 120 | + | 
|  | 121 | +				gnd->cubes = cubes; | 
|  | 122 | +				gnd->width = glm::max(1, max.x - min.x); | 
|  | 123 | +				gnd->height = glm::max(1, max.y - min.y); | 
|  | 124 | +				glm::vec3 newCenterOffset(5 * -gnd->width, 0, 5 * -gnd->height); | 
|  | 125 | + | 
|  | 126 | +				if (!settings.heightSelectionOnly && (settings.cropLeft < 0 || settings.cropBottom < 0 || settings.cropRight < 0 || settings.cropTop < 0)) | 
|  | 127 | +					gndRenderer->rebuildChunks(); | 
|  | 128 | +				else | 
|  | 129 | +					gndRenderer->setChunksDirty(); | 
|  | 130 | + | 
|  | 131 | +				activeMapView->map->tileSelection.clear(); | 
|  | 132 | +				activeMapView->map->rootNode->getComponent<WaterRenderer>()->setDirty(); | 
|  | 133 | + | 
|  | 134 | +				gat->cubes = gatCubes; | 
|  | 135 | +				gat->width = 2 * (max.x - min.x); | 
|  | 136 | +				gat->height = 2 * (max.y - min.y); | 
|  | 137 | +				activeMapView->map->rootNode->getComponent<GatRenderer>()->setChunksDirty(); | 
|  | 138 | + | 
|  | 139 | +				activeMapView->map->rootNode->traverse([&rswObjectOffset](Node* n) | 
|  | 140 | +					{ | 
|  | 141 | +						auto rsmRenderer = n->getComponent<RsmRenderer>(); | 
|  | 142 | +						if (rsmRenderer) { | 
|  | 143 | +							rsmRenderer->setDirty(); | 
|  | 144 | +						} | 
|  | 145 | +						auto rswObject = n->getComponent<RswObject>(); | 
|  | 146 | +						if (rswObject) { | 
|  | 147 | +							rswObject->position += rswObjectOffset; | 
|  | 148 | +						} | 
|  | 149 | +					}); | 
|  | 150 | + | 
|  | 151 | +				// only moves for left crop or top crop | 
|  | 152 | +				activeMapView->cameraCenter -= cameraOffset; | 
|  | 153 | + | 
|  | 154 | +				auto rsw = activeMapView->map->rootNode->getComponent<Rsw>(); | 
|  | 155 | +				delete rsw->quadtree; | 
|  | 156 | +				rsw->quadtree = new Rsw::QuadTreeNode(10 * -gnd->width / 2.0f, 10 * -gnd->height / 2.0f, (float)gnd->width * 10 - 1.0f, (float)gnd->height * 10 - 1.0f, 0); | 
|  | 157 | +				rsw->recalculateQuadtree(nullptr); | 
|  | 158 | +			} | 
|  | 159 | +		} | 
|  | 160 | +	} | 
|  | 161 | + | 
|  | 162 | +	ImGui::SameLine(); | 
|  | 163 | + | 
|  | 164 | +	if (ImGui::Button("Cancel")) | 
|  | 165 | +	{ | 
|  | 166 | +		windowData.cropWindowVisible = false; | 
|  | 167 | +	} | 
|  | 168 | +	 | 
|  | 169 | +	ImGui::End(); | 
|  | 170 | +} | 
0 commit comments