Files
OpenSpace/modules/globebrowsing/rendering/layer/layer.cpp
Kalle Bladin 7aceb54bec Globe browsing: fix implicit conversion errors and remove warnings (#393)
* Fix implicit conversion errors and remove warnings.
2017-09-01 12:03:31 -04:00

420 lines
15 KiB
C++

/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/rendering/layer/layer.h>
#include <modules/globebrowsing/rendering/layer/layergroup.h>
#include <modules/globebrowsing/rendering/layer/layermanager.h>
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
#include <modules/globebrowsing/tile/tiletextureinitdata.h>
namespace openspace::globebrowsing {
namespace {
const char* _loggerCat = "Layer";
const char* keyName = "Name";
const char* keyDescription = "Description";
const char* keyEnabled = "Enabled";
const char* keyLayerGroupID = "LayerGroupID";
const char* keySettings = "Settings";
const char* keyAdjustment = "Adjustment";
const char* KeyBlendMode = "BlendMode";
const char* KeyPadTiles = "PadTiles";
static const openspace::properties::Property::PropertyInfo TypeInfo = {
"Type",
"Type",
"The type of this Layer. This value is a read-only property and thus cannot be "
"changed."
};
static const openspace::properties::Property::PropertyInfo BlendModeInfo = {
"BlendMode",
"Blend Mode",
"This value specifies the blend mode that is applied to this layer. The blend "
"mode determines how this layer is added to the underlying layers beneath."
};
static const openspace::properties::Property::PropertyInfo EnabledInfo = {
"Enabled",
"Enabled",
"If this value is enabled, the layer will be used for the final composition of "
"the planet. If this value is disabled, the layer will be ignored in the "
"composition."
};
static const openspace::properties::Property::PropertyInfo ResetInfo = {
"Reset",
"Reset",
"If this value is triggered, this layer will be reset. This will delete the "
"local cache for this layer and will trigger a fresh load of all tiles."
};
static const openspace::properties::Property::PropertyInfo RemoveInfo = {
"Remove",
"Remove",
"If this value is triggered, a script will be executed that will remove this "
"layer before the next frame."
};
static const openspace::properties::Property::PropertyInfo ColorInfo = {
"Color",
"Color",
"If the 'Type' of this layer is a solid color, this value determines what this "
"solid color is."
};
} // namespace
Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict,
LayerGroup& parent)
: properties::PropertyOwner({
layerDict.value<std::string>(keyName),
layerDict.hasKey(keyDescription) ? layerDict.value<std::string>(keyDescription) : ""
})
, _parent(parent)
, _typeOption(TypeInfo, properties::OptionProperty::DisplayType::Dropdown)
, _blendModeOption(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
, _enabled(EnabledInfo, false)
, _reset(ResetInfo)
, _remove(RemoveInfo)
, _tileProvider(nullptr)
, _otherTypesProperties({
{ ColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f) }
})
, _layerGroupId(id)
{
layergroupid::TypeID typeID = parseTypeIdFromDictionary(layerDict);
if (typeID == layergroupid::TypeID::Unknown) {
throw ghoul::RuntimeError("Unknown layer type!");
}
initializeBasedOnType(typeID, layerDict);
bool enabled = false; // defaults to false if unspecified
layerDict.getValue(keyEnabled, enabled);
_enabled.setValue(enabled);
bool padTiles = true;
layerDict.getValue<bool>(KeyPadTiles, padTiles);
TileTextureInitData initData = LayerManager::getTileTextureInitData(_layerGroupId,
padTiles);
_padTilePixelStartOffset = initData.tilePixelStartOffset();
_padTilePixelSizeDifference = initData.tilePixelSizeDifference();
// Initialize settings
ghoul::Dictionary settingsDict;
if (layerDict.getValue(keySettings, settingsDict)) {
_renderSettings.setValuesFromDictionary(settingsDict);
}
// Initiallize layer adjustment
ghoul::Dictionary adjustmentDict;
if (layerDict.getValue(keyAdjustment, adjustmentDict)) {
_layerAdjustment.setValuesFromDictionary(adjustmentDict);
}
// Add options to option properties
for (int i = 0; i < layergroupid::NUM_LAYER_TYPES; ++i) {
_typeOption.addOption(i, layergroupid::LAYER_TYPE_NAMES[i]);
}
_typeOption.setValue(static_cast<int>(typeID));
_type = static_cast<layergroupid::TypeID>(_typeOption.value());
for (int i = 0; i < layergroupid::NUM_BLEND_MODES; ++i) {
_blendModeOption.addOption(i, layergroupid::BLEND_MODE_NAMES[i]);
}
// Initialize blend mode
std::string blendModeName;
if (layerDict.getValue(KeyBlendMode, blendModeName)) {
layergroupid::BlendModeID blendModeID =
layergroupid::getBlendModeIDFromName(blendModeName);
_blendModeOption.setValue(static_cast<int>(blendModeID));
}
else {
_blendModeOption.setValue(static_cast<int>(layergroupid::BlendModeID::Normal));
}
// On change callbacks definitions
_enabled.onChange([&](){
if (_onChangeCallback) {
_onChangeCallback();
}
});
_reset.onChange([&](){
if (_tileProvider) {
_tileProvider->reset();
}
});
_remove.onChange([&](){
if (_tileProvider) {
_tileProvider->reset();
}
_parent.deleteLayer(name());
});
_typeOption.onChange([&](){
removeVisibleProperties();
_type = static_cast<layergroupid::TypeID>(_typeOption.value());
ghoul::Dictionary dict;
initializeBasedOnType(type(), dict);
addVisibleProperties();
if (_onChangeCallback) {
_onChangeCallback();
}
});
_blendModeOption.onChange([&](){
if (_onChangeCallback) {
_onChangeCallback();
}
});
_layerAdjustment.onChange([&](){
if (_onChangeCallback) {
_onChangeCallback();
}
});
_typeOption.setReadOnly(true);
// Add the properties
addProperty(_typeOption);
addProperty(_blendModeOption);
addProperty(_enabled);
addProperty(_reset);
addProperty(_remove);
_otherTypesProperties.color.setViewOption(properties::Property::ViewOptions::Color);
addVisibleProperties();
addPropertySubOwner(_renderSettings);
addPropertySubOwner(_layerAdjustment);
}
ChunkTilePile Layer::getChunkTilePile(const TileIndex& tileIndex, int pileSize) const {
if (_tileProvider) {
return _tileProvider->getChunkTilePile(tileIndex, pileSize);
}
else {
ChunkTilePile chunkTilePile;
chunkTilePile.resize(pileSize);
for (int i = 0; i < pileSize; ++i) {
chunkTilePile[i].tile = Tile::TileUnavailable;
chunkTilePile[i].uvTransform.uvOffset = { 0, 0 };
chunkTilePile[i].uvTransform.uvScale = { 1, 1 };
}
return chunkTilePile;
}
}
Tile::Status Layer::getTileStatus(const TileIndex& index) const {
if (_tileProvider) {
return _tileProvider->getTileStatus(index);
}
else {
return Tile::Status::Unavailable;
}
}
layergroupid::TypeID Layer::type() const {
return _type;
}
layergroupid::BlendModeID Layer::blendMode() const {
return static_cast<layergroupid::BlendModeID>(_blendModeOption.value());
}
TileDepthTransform Layer::depthTransform() const {
if (_tileProvider) {
return _tileProvider->depthTransform();
}
else {
return {1.0f, 0.0f};
}
}
bool Layer::enabled() const {
return _enabled.value();
}
tileprovider::TileProvider* Layer::tileProvider() const {
return _tileProvider.get();
}
const Layer::OtherTypesProperties& Layer::otherTypesProperties() const {
return _otherTypesProperties;
}
const LayerRenderSettings& Layer::renderSettings() const {
return _renderSettings;
}
const LayerAdjustment& Layer::layerAdjustment() const {
return _layerAdjustment;
}
void Layer::onChange(std::function<void(void)> callback) {
_onChangeCallback = callback;
}
void Layer::update() {
if (_tileProvider) {
_tileProvider->update();
}
}
glm::ivec2 Layer::tilePixelStartOffset() const {
return _padTilePixelStartOffset;
}
glm::ivec2 Layer::tilePixelSizeDifference() const {
return _padTilePixelSizeDifference;
}
glm::vec2 Layer::compensateSourceTextureSampling(glm::vec2 startOffset, glm::vec2 sizeDiff,
glm::uvec2 resolution, glm::vec2 tileUV)
{
glm::vec2 sourceSize = glm::vec2(resolution) + sizeDiff;
glm::vec2 currentSize = glm::vec2(resolution);
glm::vec2 sourceToCurrentSize = currentSize / sourceSize;
tileUV = sourceToCurrentSize * (tileUV - startOffset / sourceSize);
return tileUV;
}
glm::vec2 Layer::TileUvToTextureSamplePosition(const TileUvTransform& uvTransform,
glm::vec2 tileUV, glm::uvec2 resolution)
{
glm::vec2 uv = uvTransform.uvOffset + uvTransform.uvScale * tileUV;
uv = compensateSourceTextureSampling(
tilePixelStartOffset(),
tilePixelSizeDifference(),
resolution,
uv);
return uv;
}
layergroupid::TypeID Layer::parseTypeIdFromDictionary(
const ghoul::Dictionary& initDict) const
{
if (initDict.hasKeyAndValue<std::string>("Type")) {
const std::string typeString = initDict.value<std::string>("Type");
return layergroupid::getTypeIDFromTypeString(typeString);
}
else {
return layergroupid::TypeID::DefaultTileLayer;
}
}
void Layer::initializeBasedOnType(layergroupid::TypeID typeId, ghoul::Dictionary initDict) {
switch (typeId) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer: {
// We add the id to the dictionary since it needs to be known by
// the tile provider
ghoul::Dictionary tileProviderInitDict = initDict;
tileProviderInitDict.setValue(keyLayerGroupID, _layerGroupId);
if (tileProviderInitDict.hasKeyAndValue<std::string>(keyName)) {
std::string name;
tileProviderInitDict.getValue(keyName, name);
LDEBUG("Initializing tile provider for layer: '" + name + "'");
}
_tileProvider = std::shared_ptr<tileprovider::TileProvider>(
tileprovider::TileProvider::createFromDictionary(typeId, tileProviderInitDict)
);
break;
}
case layergroupid::TypeID::SolidColor: {
if (initDict.hasKeyAndValue<glm::vec3>(ColorInfo.identifier)) {
glm::vec3 color;
initDict.getValue(ColorInfo.identifier, color);
_otherTypesProperties.color.setValue(color);
}
break;
}
default:
throw ghoul::RuntimeError("Unable to create layer. Unknown type.");
}
}
void Layer::addVisibleProperties() {
switch (type()) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer: {
if (_tileProvider) {
addPropertySubOwner(*_tileProvider);
}
break;
}
case layergroupid::TypeID::SolidColor: {
addProperty(_otherTypesProperties.color);
break;
}
default:
break;
}
}
void Layer::removeVisibleProperties() {
switch (type()) {
// Intentional fall through. Same for all tile layers
case layergroupid::TypeID::DefaultTileLayer:
case layergroupid::TypeID::SingleImageTileLayer:
case layergroupid::TypeID::SizeReferenceTileLayer:
case layergroupid::TypeID::TemporalTileLayer:
case layergroupid::TypeID::TileIndexTileLayer:
case layergroupid::TypeID::ByIndexTileLayer:
case layergroupid::TypeID::ByLevelTileLayer:
if (_tileProvider) {
removePropertySubOwner(*_tileProvider);
}
break;
case layergroupid::TypeID::SolidColor:
removeProperty(_otherTypesProperties.color);
break;
default:
break;
}
}
} // namespace openspace::globebrowsing