Skip to content

Commit

Permalink
#5168: Change MapPosition class to store properties to the map root's…
Browse files Browse the repository at this point in the history
… property bag immediately. DR no longer stores the map position as dummy spawnargs to the worldspawn, since we now have a property store in the map root to hold them. Legacy key values found on worldspawn are automatically converted to root properties on map load.

Add events to MapExport class to be able to inject data to the exported scene, regardless of the format or what type of scene is exported.
  • Loading branch information
codereader committed Apr 19, 2020
1 parent 91069c0 commit bba97e3
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 123 deletions.
1 change: 1 addition & 0 deletions radiant/map/Map.cpp
Expand Up @@ -830,6 +830,7 @@ void Map::initialiseModule(const ApplicationContext& ctx)

void Map::shutdownModule()
{
MapExporter::cleanupEvents();
_scaledModelExporter.shutdown();

GlobalSceneGraph().removeSceneObserver(this);
Expand Down
143 changes: 100 additions & 43 deletions radiant/map/MapPosition.cpp
Expand Up @@ -7,11 +7,15 @@
#include "map/Map.h"
#include "gamelib.h"

namespace map {
namespace map
{

namespace {
const std::string GKEY_MAP_POSROOT = "/mapFormat/mapPositionPosKey";
const std::string GKEY_MAP_ANGLEROOT = "/mapFormat/mapPositionAngleKey";
namespace
{
const char* const GKEY_MAP_POSROOT = "/mapFormat/mapPositionPosKey";
const char* const GKEY_MAP_ANGLEROOT = "/mapFormat/mapPositionAngleKey";
const char* const POSITION_KEY_FORMAT = "MapPosition{0:d}";
const char* const ANGLE_KEY_FORMAT = "MapAngle{0:d}";
}

MapPosition::MapPosition(unsigned int index) :
Expand All @@ -24,79 +28,132 @@ MapPosition::MapPosition(unsigned int index) :
_angleKey = game::current::getValue<std::string>(GKEY_MAP_ANGLEROOT) + string::to_string(_index);
}

void MapPosition::load(Entity* entity)
void MapPosition::loadFrom(Entity* entity)
{
// Sanity check
if (entity != NULL)
if (entity == nullptr) return;

const std::string savedPos = entity->getKeyValue(_posKey);

if (!savedPos.empty())
{
const std::string savedPos = entity->getKeyValue(_posKey);

if (savedPos != "")
{
// Construct the vectors out of the std::string
_position = string::convert<Vector3>(savedPos);
_angle = string::convert<Vector3>(entity->getKeyValue(_angleKey));
}
// Parse the vectors from std::string
_position = string::convert<Vector3>(savedPos);
_angle = string::convert<Vector3>(entity->getKeyValue(_angleKey));
}
}

void MapPosition::save(Entity* entity)
void MapPosition::removeFrom(Entity* entity)
{
// Sanity check
if (entity == NULL) return;
if (entity != nullptr)
{
entity->setKeyValue(_posKey, "");
entity->setKeyValue(_angleKey, "");
}
}

void MapPosition::loadFrom(const scene::IMapRootNodePtr& root)
{
assert(root);

auto pos = root->getProperty(fmt::format(POSITION_KEY_FORMAT, _index));

if (!pos.empty())
{
// Parse the vectors from std::string
_position = string::convert<Vector3>(pos);

auto angle = root->getProperty(fmt::format(ANGLE_KEY_FORMAT, _index));
_angle = string::convert<Vector3>(angle);
}
}

void MapPosition::saveTo(const scene::IMapRootNodePtr& root)
{
assert(root);

if (!empty())
{
rMessage() << "Saving to key: " << _posKey << std::endl;
entity->setKeyValue(_posKey, string::to_string(_position));
entity->setKeyValue(_angleKey, string::to_string(_angle));
root->setProperty(fmt::format(POSITION_KEY_FORMAT, _index), string::to_string(_position));
root->setProperty(fmt::format(ANGLE_KEY_FORMAT, _index), string::to_string(_angle));
}
else
{
// This is an empty position, clear the values
remove(entity);
removeFrom(root);
}
}

void MapPosition::remove(Entity* entity) {
// Sanity check
if (entity != NULL) {
entity->setKeyValue(_posKey, "");
entity->setKeyValue(_angleKey, "");
}
void MapPosition::removeFrom(const scene::IMapRootNodePtr& root)
{
root->removeProperty(fmt::format(POSITION_KEY_FORMAT, _index));
root->removeProperty(fmt::format(ANGLE_KEY_FORMAT, _index));
}

void MapPosition::clear() {
void MapPosition::clear()
{
_position = Vector3(0,0,0);
_angle = Vector3(0,0,0);
}

bool MapPosition::empty() const {
return (_position == Vector3(0,0,0) && _angle == Vector3(0,0,0));
bool MapPosition::empty() const
{
return _position == Vector3(0,0,0) && _angle == Vector3(0,0,0);
}

void MapPosition::store(const cmd::ArgumentList& args) {
rMessage() << "Storing map position #" << _index << std::endl;
ui::CamWndPtr camwnd = GlobalCamera().getActiveCamWnd();

if (camwnd != NULL) {
_position = camwnd->getCameraOrigin();
_angle = camwnd->getCameraAngles();
void MapPosition::store(const cmd::ArgumentList& args)
{
auto mapRoot = GlobalMapModule().getRoot();

// Tag the map as modified
GlobalMap().setModified(true);
if (!mapRoot)
{
rError() << "Cannot store map position, no map loaded." << std::endl;
return;
}
else {
rError() << "MapPosition: Warning: Couldn't find Camera." << std::endl;

rMessage() << "Storing map position #" << _index << std::endl;

auto camwnd = GlobalCamera().getActiveCamWnd();

if (!camwnd)
{
rWarning() << "MapPosition: Couldn't find Camera." << std::endl;
return;
}

_position = camwnd->getCameraOrigin();
_angle = camwnd->getCameraAngles();

saveTo(mapRoot);

// Tag the map as modified
GlobalMap().setModified(true);
}

void MapPosition::recall(const cmd::ArgumentList& args) {
if (!empty()) {
void MapPosition::recall(const cmd::ArgumentList& args)
{
auto mapRoot = GlobalMapModule().getRoot();

if (!mapRoot)
{
rError() << "Cannot recall map position, no map loaded." << std::endl;
return;
}

// Refresh our local data from the properties
loadFrom(mapRoot);

if (!empty())
{
rMessage() << "Restoring map position #" << _index << std::endl;

// Focus the view with the default angle
Map::focusViews(_position, _angle);
}
else
{
rMessage() << "Map position #" << _index << " has not been set" << std::endl;
}
}

} // namespace map
28 changes: 14 additions & 14 deletions radiant/map/MapPosition.h
@@ -1,14 +1,15 @@
#ifndef MAPPOSITION_H_
#define MAPPOSITION_H_
#pragma once

#include <string>
#include "icommandsystem.h"
#include "imap.h"
#include "math/Vector3.h"
#include <memory>

class Entity;

namespace map {
namespace map
{

/** greebo: An instance of such a class manages a single Map Position.
*
Expand All @@ -33,18 +34,19 @@ class MapPosition

/** greebo: Loads the position from the given entity
*/
void load(Entity* entity);

/** greebo: Saves the position to the given entity.
*
* If this position is empty, the keys/values are
* removed from the entity.
*/
void save(Entity* entity);
void loadFrom(Entity* entity);

/** greebo: Removes the values from the given entity
*/
void remove(Entity* entity);
void removeFrom(Entity* entity);

void loadFrom(const scene::IMapRootNodePtr& root);

// Store the current position to the map root
void saveTo(const scene::IMapRootNodePtr& root);

// Remove the current position from the given node
void removeFrom(const scene::IMapRootNodePtr& root);

/** greebo: Resets the position/angles to 0,0,0
*/
Expand All @@ -67,5 +69,3 @@ class MapPosition
typedef std::shared_ptr<MapPosition> MapPositionPtr;

} // namespace map

#endif /*MAPPOSITION_H_*/

0 comments on commit bba97e3

Please sign in to comment.