5 #include <unordered_map>
6 #include <unordered_set>
42 using std::make_unique;
44 using std::unique_ptr;
45 using std::unordered_map;
46 using std::unordered_set;
82 TerrainEditorTabView::TerrainEditorTabView(
EditorView* editorView,
const string& tabId,
Prototype* prototype)
87 this->prototype = unique_ptr<Prototype>(
prototype);
88 engine = unique_ptr<Engine>(Engine::createOffScreenInstance(512, 512,
true,
true,
true));
89 engine->setSceneColor(
Color4(39.0f / 255.0f, 39.0f / 255.0f, 39.0f / 255.0f, 1.0f));
90 engine->setSkyShaderEnabled(
true);
91 SceneConnector::setNaturalLights(
engine.get());
102 for (
auto& event:
engine->getGUI()->getMouseEvents()) {
103 if (event.isProcessed() ==
true)
continue;
105 if (event.getType() == GUIMouseEvent::MOUSEEVENT_WHEEL_MOVED) {
106 if (event.isShiftDown() ==
true) {
108 event.setProcessed(
true);
110 if (event.isControlDown() ==
true) {
112 event.setProcessed(
true);
115 if (event.getType() == GUIMouseEvent::MOUSEEVENT_MOVED) {
123 engine->setShaderParameter(
"terraineditor",
"brushEnabled", brushEnabled);
124 if (brushEnabled ==
true) {
127 engine->setShaderParameter(
"terraineditor",
"brushRotation", brushRotation);
128 engine->setShaderParameter(
"terraineditor",
"brushScale",
130 (
brushScale * 5.0f) /
engine->getShaderParameter(
"terraineditor",
"brushDimension").getVector2Value().getX(),
131 1.0f / (
engine->getShaderParameter(
"terraineditor",
"brushDimension").getVector2Value().getY() /
rampVertices[1].clone().sub(
rampVertices[0]).computeLength())
138 if (event.getType() == GUIMouseEvent::MOUSEEVENT_RELEASED) {
141 engine->setShaderParameter(
"terraineditor",
"brushEnabled",
false);
142 engine->setShaderParameter(
"terraineditor",
"brushRotation", 0.0f);
143 engine->setShaderParameter(
"terraineditor",
"brushScale",
Vector2(1.0f, 1.0f));
145 event.setProcessed(
true);
149 if (event.getType() == GUIMouseEvent::MOUSEEVENT_RELEASED) {
166 engine->getShaderParameter(
"terraineditor",
"brushRotation").getFloatValue(),
167 engine->getShaderParameter(
"terraineditor",
"brushScale").getVector2Value(),
173 engine->setShaderParameter(
"terraineditor",
"brushEnabled",
false);
174 engine->setShaderParameter(
"terraineditor",
"brushRotation", 0.0f);
175 engine->setShaderParameter(
"terraineditor",
"brushScale",
Vector2(1.0f, 1.0f));
184 event.setProcessed(
true);
186 if (event.getType() == GUIMouseEvent::MOUSEEVENT_PRESSED ||
187 event.getType() == GUIMouseEvent::MOUSEEVENT_DRAGGED) {
197 vector<Model*> waterModels;
198 Vector3 waterReflectionEnvironmentMappingPosition;
203 for (
auto waterModel: waterModels) {
204 auto waterObject =
new Object(waterModel->getId(), waterModel);
205 waterObject->setRenderPass(Entity::RENDERPASS_WATER);
206 waterObject->setShader(
"water");
207 waterObject->setContributesShadows(
false);
208 waterObject->setReceivesShadows(
false);
209 waterObject->setReflectionEnvironmentMappingId(
"sky_environment_mapping");
210 waterObject->setReflectionEnvironmentMappingPosition(waterReflectionEnvironmentMappingPosition);
211 waterObject->setPickable(
true);
212 engine->addEntity(waterObject);
217 auto selectedEntity =
engine->getEntityByMousePosition(event.getXUnscaled(), event.getYUnscaled());
218 if (selectedEntity !=
nullptr && StringTools::startsWith(selectedEntity->getId(),
"water.") ==
true) {
219 auto waterBeginIdx = selectedEntity->getId().find(
'.', selectedEntity->getId().find(
'.') + 1) + 1;
220 auto waterEndIdx = selectedEntity->getId().find(
'.', waterBeginIdx + 1);
221 auto waterPositionMapIdx = Integer::parse(StringTools::substring(selectedEntity->getId(), waterBeginIdx, waterEndIdx));
229 event.setProcessed(
true);
233 for (
auto& event:
engine->getGUI()->getKeyboardEvents()) {
234 if (event.isProcessed() ==
true)
continue;
235 if (event.getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_TYPED)
continue;
236 auto isKeyDown =
event.getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED;
237 if (event.getKeyCode() == GUIKeyboardEvent::KEYCODE_ESCAPE) {
238 if (isKeyDown ==
true) {
241 engine->setShaderParameter(
"terraineditor",
"brushEnabled",
false);
242 engine->setShaderParameter(
"terraineditor",
"brushRotation", 0.0f);
243 engine->setShaderParameter(
"terraineditor",
"brushScale",
Vector2(1.0f, 1.0f));
246 event.setProcessed(
true);
282 Console::println(
"TerrainEditorTabView::initialize(): An error occurred: " +
string(exception.what()));
322 PrototypeWriter::write(pathName, fileName,
prototype.get());
332 auto environmentMapping =
new EnvironmentMapping(
"sky_environment_mapping", Engine::getEnvironmentMappingWidth(), Engine::getEnvironmentMappingHeight(),
BoundingBox(
Vector3(-30.0f, 0.0f, -30.0f),
Vector3(30.0f, 60.0f, -30.0f)));
333 environmentMapping->setFrustumCulling(
false);
334 environmentMapping->setRenderPassMask(Entity::RENDERPASS_NOFRUSTUMCULLING);
335 environmentMapping->setTimeRenderUpdateFrequency(33LL);
336 environmentMapping->update();
337 engine->addEntity(environmentMapping);
354 auto terrainObject =
new Object(
"terrain." + to_string(idx), terrainModel);
355 terrainObject->setRequiresPreRender(
true);
356 terrainObject->setRenderPass(Entity::RENDERPASS_TERRAIN);
357 terrainObject->setShader(
"terraineditor");
358 terrainObject->setContributesShadows(
true);
359 terrainObject->setReceivesShadows(
true);
360 terrainObject->setPickable(
true);
361 engine->addEntity(terrainObject);
371 if (
waters.empty() ==
false) {
372 for (
const auto& [waterIdx, water]:
waters) {
373 for (
const auto waterModel: water.waterModels) {
374 auto waterObject =
new Object(waterModel->getId(), waterModel);
375 waterObject->setRenderPass(Entity::RENDERPASS_WATER);
376 waterObject->setShader(
"water");
377 waterObject->setContributesShadows(
false);
378 waterObject->setReceivesShadows(
false);
379 waterObject->setReflectionEnvironmentMappingId(
"sky_environment_mapping");
380 waterObject->setReflectionEnvironmentMappingPosition(water.waterReflectionEnvironmentMappingPosition);
381 waterObject->setPickable(
true);
382 engine->addEntity(waterObject);
392 for (
const auto& [waterIdx, water]:
waters) {
393 for (
const auto waterModel: water.waterModels) {
394 engine->removeEntity(waterModel->getId());
398 this->waters.clear();
405 const auto& foliageMaps =
prototype->getTerrain()->getFoliageMaps();
408 auto partitionIdx = 0;
409 for (
auto& foliageMapPartition: foliageMaps) {
410 engine->removeEntity(
"foliage.entityhierarchy." + to_string(partitionIdx));
411 auto shaderParameterIdx = 0;
412 while (
engine->removeEntity(
"foliage.objectrendergroup." + to_string(partitionIdx) +
"." + to_string(shaderParameterIdx)) ==
true) shaderParameterIdx++;
413 auto partitionPrototypeInstanceCount = 0;
414 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
415 partitionPrototypeInstanceCount+= transformVector.size();
417 if (partitionPrototypeInstanceCount > 0) {
418 unordered_map<string, ObjectRenderGroup*> objectRenderGroupByShaderParameters;
419 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
420 if (transformVector.empty() ==
false) {
421 auto foliagePrototype =
prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
423 auto foliagePartitionObjectRenderGroupIt = objectRenderGroupByShaderParameters.find(foliagePrototype->getShaderParameters().getShaderParametersHash());
424 if (foliagePartitionObjectRenderGroupIt != objectRenderGroupByShaderParameters.end()) {
425 foliagePartitionObjectRenderGroup = foliagePartitionObjectRenderGroupIt->second;
427 if (foliagePartitionObjectRenderGroup ==
nullptr) {
429 "foliage.objectrendergroup." + to_string(partitionIdx) +
"." + to_string(objectRenderGroupByShaderParameters.size()),
439 foliagePartitionObjectRenderGroup->
setShader(foliagePrototype->getShader());
440 for (
const auto& parameterName: Engine::getShaderParameterNames(foliagePrototype->getShader())) {
441 auto parameterValue = foliagePrototype->getShaderParameters().getShaderParameter(parameterName);
444 engine->addEntity(foliagePartitionObjectRenderGroup);
445 objectRenderGroupByShaderParameters[foliagePrototype->getShaderParameters().getShaderParametersHash()] = foliagePartitionObjectRenderGroup;
447 for (
const auto& transform: transformVector) {
448 foliagePartitionObjectRenderGroup->
addObject(foliagePrototype->getModel(), transform);
452 for (
const auto& [shaderHash, objectRenderGroup]: objectRenderGroupByShaderParameters) {
453 objectRenderGroup->updateRenderGroup();
464 const auto& foliageMaps =
prototype->getTerrain()->getFoliageMaps();
467 auto partitionIdx = 0;
468 for (
auto& foliageMapPartition: newFoliageMaps) {
469 auto partitionPrototypeInstanceCount = 0;
470 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
471 partitionPrototypeInstanceCount+= transformVector.size();
473 if (partitionPrototypeInstanceCount > 0) {
478 auto foliagePartitionObjectRenderGroup =
engine->getEntity(
"foliage.objectrendergroup." + to_string(partitionIdx) +
".0");
479 if (foliagePartitionObjectRenderGroup !=
nullptr) {
480 auto shaderParameterIdx = 0;
481 while (
engine->removeEntity(
"foliage.objectrendergroup." + to_string(partitionIdx) +
"." + to_string(shaderParameterIdx)) ==
true) shaderParameterIdx++;
484 auto foliagePartitionEntityHierarchy =
dynamic_cast<EntityHierarchy*
>(
engine->getEntity(
"foliage.entityhierarchy." + to_string(partitionIdx)));
485 if (foliagePartitionEntityHierarchy ==
nullptr) {
486 foliagePartitionEntityHierarchy =
new EntityHierarchy(
"foliage.entityhierarchy." + to_string(partitionIdx));
487 foliagePartitionEntityHierarchy->setContributesShadows(
true);
488 foliagePartitionEntityHierarchy->setReceivesShadows(
true);
489 engine->addEntity(foliagePartitionEntityHierarchy);
491 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
492 if (transformVector.empty() ==
false) {
493 auto foliagePrototype =
prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
495 for (
const auto& transform: transformVector) {
496 auto foliageEntity = SceneConnector::createEntity(foliagePrototype, foliagePartitionEntityHierarchy->getId() +
"." + to_string(prototypeIdx) +
"." + to_string(foliageIdx), transform);
497 foliagePartitionEntityHierarchy->addEntity(foliageEntity);
502 foliagePartitionEntityHierarchy->update();
512 const auto& foliageMaps =
prototype->getTerrain()->getFoliageMaps();
515 auto partitionIdx = 0;
516 for (
auto partitionIdx: partitionIdxSet) {
517 const auto& foliageMapPartition = foliageMaps[partitionIdx];
518 auto partitionPrototypeInstanceCount = 0;
519 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
520 partitionPrototypeInstanceCount+= transformVector.size();
522 if (partitionPrototypeInstanceCount > 0) {
527 auto foliagePartitionObjectRenderGroup =
engine->getEntity(
"foliage.objectrendergroup." + to_string(partitionIdx) +
".0");
528 auto foliagePartitionEntityHierarchy =
dynamic_cast<EntityHierarchy*
>(
engine->getEntity(
"foliage.entityhierarchy." + to_string(partitionIdx)));
529 if (foliagePartitionObjectRenderGroup !=
nullptr || foliagePartitionEntityHierarchy ==
nullptr) {
530 auto shaderParameterIdx = 0;
531 while (
engine->removeEntity(
"foliage.objectrendergroup." + to_string(partitionIdx) +
"." + to_string(shaderParameterIdx)) ==
true) shaderParameterIdx++;
534 if (foliagePartitionEntityHierarchy ==
nullptr) foliagePartitionEntityHierarchy =
dynamic_cast<EntityHierarchy*
>(
engine->getEntity(
"foliage.entityhierarchy." + to_string(partitionIdx)));
536 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
537 for (
const auto& transform: transformVector) {
538 foliagePartitionEntityHierarchy->
getEntities()[foliageIdx]->setTransform(transform);
542 foliagePartitionEntityHierarchy->update();
555 const auto& foliageMaps =
prototype->getTerrain()->getFoliageMaps();
558 const auto& foliageMapPartition = foliageMaps[partitionIdx];
559 engine->removeEntity(
"foliage.entityhierarchy." + to_string(partitionIdx));
560 auto shaderParameterIdx = 0;
561 while (
engine->removeEntity(
"foliage.objectrendergroup." + to_string(partitionIdx) +
"." + to_string(shaderParameterIdx)) ==
true) shaderParameterIdx++;
562 auto partitionPrototypeInstanceCount = 0;
563 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
564 partitionPrototypeInstanceCount+= transformVector.size();
566 if (partitionPrototypeInstanceCount > 0) {
567 auto foliagePartitionEntityHierarchy =
new EntityHierarchy(
"foliage.entityhierarchy." + to_string(partitionIdx));
568 foliagePartitionEntityHierarchy->setContributesShadows(
true);
569 foliagePartitionEntityHierarchy->setReceivesShadows(
true);
570 engine->addEntity(foliagePartitionEntityHierarchy);
571 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
572 auto foliagePrototype =
prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
574 for (
const auto& transform: transformVector) {
575 auto foliageEntity = SceneConnector::createEntity(foliagePrototype, foliagePartitionEntityHierarchy->getId() +
"." + to_string(prototypeIdx) +
"." + to_string(foliageIdx), transform);
576 foliagePartitionEntityHierarchy->addEntity(foliageEntity);
580 foliagePartitionEntityHierarchy->update();
588 auto& foliageMaps =
prototype->getTerrain()->getFoliageMaps();
591 for (
auto partitionIdx: partitionIdxSet) {
592 const auto& foliageMapPartition = foliageMaps[partitionIdx];
593 engine->removeEntity(
"foliage.entityhierarchy." + to_string(partitionIdx));
594 auto shaderParameterIdx = 0;
595 while (
engine->removeEntity(
"foliage.objectrendergroup." + to_string(partitionIdx) +
"." + to_string(shaderParameterIdx)) ==
true) shaderParameterIdx++;
596 auto partitionPrototypeInstanceCount = 0;
597 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
598 partitionPrototypeInstanceCount+= transformVector.size();
600 if (partitionPrototypeInstanceCount > 0) {
601 unordered_map<string, ObjectRenderGroup*> objectRenderGroupByShaderParameters;
602 for (
const auto& [prototypeIdx, transformVector]: foliageMapPartition) {
603 if (transformVector.empty() ==
false) {
604 auto foliagePrototype =
prototype->getTerrain()->getFoliagePrototype(prototypeIdx);
606 auto foliagePartitionObjectRenderGroupIt = objectRenderGroupByShaderParameters.find(foliagePrototype->getShaderParameters().getShaderParametersHash());
607 if (foliagePartitionObjectRenderGroupIt != objectRenderGroupByShaderParameters.end()) {
608 foliagePartitionObjectRenderGroup = foliagePartitionObjectRenderGroupIt->second;
610 if (foliagePartitionObjectRenderGroup ==
nullptr) {
612 "foliage.objectrendergroup." + to_string(partitionIdx) +
"." + to_string(objectRenderGroupByShaderParameters.size()),
622 foliagePartitionObjectRenderGroup->
setShader(foliagePrototype->getShader());
623 for (
const auto& parameterName: Engine::getShaderParameterNames(foliagePrototype->getShader())) {
624 auto parameterValue = foliagePrototype->getShaderParameters().getShaderParameter(parameterName);
627 engine->addEntity(foliagePartitionObjectRenderGroup);
628 objectRenderGroupByShaderParameters[foliagePrototype->getShaderParameters().getShaderParametersHash()] = foliagePartitionObjectRenderGroup;
630 for (
const auto& transform: transformVector) {
631 foliagePartitionObjectRenderGroup->
addObject(foliagePrototype->getModel(), transform);
635 for (
const auto& [shaderHash, objectRenderGroup]: objectRenderGroupByShaderParameters) {
636 objectRenderGroup->updateRenderGroup();
643 const auto& water =
waters[waterIdx];
644 for (
auto waterModel: water.waterModels) {
645 engine->removeEntity(waterModel->getId());
652 auto& water =
waters[waterIdx];
653 for (
auto waterModel: water.waterModels) {
654 engine->removeEntity(waterModel->getId());
657 water.waterModels = waterModels;
658 water.waterReflectionEnvironmentMappingPosition = waterReflectionEnvironmentMappingPosition;
662 for (
auto terrainModel: this->
terrainModels)
delete terrainModel;
664 this->terrainModels.clear();
688 engine->setShaderParameter(
694 if (texture ==
nullptr)
return;
723 engine->setShaderParameter(
"terraineditor",
"brushEnabled",
false);
Color 4 definition class.
Entity hierarchy to be used with engine class.
const vector< Entity * > & getEntities()
Environment mapping entity.
Object render group for static objects that might be animated by shaders.
void setShader(const string &id)
Set shader id.
void setReceivesShadows(bool receivesShadows) override
Enable/disable receives shadows.
void setShaderParameter(const string ¶meterName, const ShaderParameter ¶meterValue)
Set shader parameter for given parameter name.
void addObject(Model *model, const Transform &transform)
Adds a instance to this render group.
void setContributesShadows(bool contributesShadows) override
Enable/disable contributes shadows.
Object to be used with engine class.
Scene engine/physics connector.
const string & getId() const
uint16_t getTextureHeight() const
uint16_t getTextureWidth() const
Represents specular material properties.
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
const Vector3 & getCenter() const
Prototype terrain definition.
GUI screen node that represents a screen that can be rendered via GUI system.
Vector2 class representing vector2 mathematical structure and operations with x, y components.
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Vector3 & set(float x, float y, float z)
Sets this vector3 by its components.
Mutable utf8 aware string class.
MutableString & append(char c)
Append character.
virtual void releaseReference()
Releases a reference, thus decrementing the counter and delete it if reference counter is zero.
virtual void acquireReference()
Acquires a reference, incrementing the counter.
std::exception Exception
Exception base class.