2018-07-31 22:43:41 +02:00
|
|
|
/*
|
|
|
|
|
Copyright (C) 2018 Erik Ogenvik
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-10-15 22:06:53 +02:00
|
|
|
#include <common/Inheritance.h>
|
2018-10-31 21:38:35 +01:00
|
|
|
#include "rules/entityfilter/Providers.h"
|
2018-07-31 22:43:41 +02:00
|
|
|
#include "UsageInstance.h"
|
2018-10-31 21:38:35 +01:00
|
|
|
#include "rules/LocatedEntity.h"
|
|
|
|
|
#include "rules/simulation/BaseWorld.h"
|
2018-08-20 22:10:46 +02:00
|
|
|
#include "modules/Variant.h"
|
2018-07-31 22:43:41 +02:00
|
|
|
|
|
|
|
|
using Atlas::Message::Element;
|
|
|
|
|
using Atlas::Message::ListType;
|
|
|
|
|
using Atlas::Message::MapType;
|
|
|
|
|
using Atlas::Objects::Root;
|
|
|
|
|
using Atlas::Objects::Operation::Action;
|
|
|
|
|
using Atlas::Objects::Operation::Use;
|
|
|
|
|
using Atlas::Objects::Entity::Anonymous;
|
|
|
|
|
using Atlas::Objects::Entity::RootEntity;
|
|
|
|
|
|
2018-11-03 16:43:33 +01:00
|
|
|
std::function<Py::Object(UsageInstance&& usageInstance)> UsageInstance::scriptCreator;
|
2018-08-20 22:10:46 +02:00
|
|
|
|
2018-07-31 22:43:41 +02:00
|
|
|
std::pair<bool, std::string> UsageInstance::isValid() const
|
|
|
|
|
{
|
2018-08-03 22:32:07 +02:00
|
|
|
|
|
|
|
|
if (definition.constraint) {
|
2018-08-05 20:47:09 +02:00
|
|
|
EntityFilter::QueryContext queryContext{*tool, actor.get(), tool.get()};
|
2018-08-20 22:10:46 +02:00
|
|
|
queryContext.entity_lookup_fn = [](const std::string& id) { return BaseWorld::instance().getEntity(id); };
|
2018-10-15 22:06:53 +02:00
|
|
|
queryContext.type_lookup_fn = [](const std::string& id) { return Inheritance::instance().getType(id); };
|
2018-08-03 22:32:07 +02:00
|
|
|
|
|
|
|
|
if (!definition.constraint->match(queryContext)) {
|
|
|
|
|
return {false, "Constraint does not match."};
|
|
|
|
|
}
|
2018-07-31 22:43:41 +02:00
|
|
|
}
|
|
|
|
|
|
2018-08-20 22:10:46 +02:00
|
|
|
for (auto& param : definition.params) {
|
|
|
|
|
auto I = args.find(param.first);
|
|
|
|
|
if (I == args.end()) {
|
|
|
|
|
return {false, String::compose("Could not find required '%1' argument.", param.first)};
|
2018-07-31 22:43:41 +02:00
|
|
|
}
|
2018-08-20 22:10:46 +02:00
|
|
|
int count = 0;
|
|
|
|
|
for (auto& arg : I->second) {
|
|
|
|
|
bool is_valid = false;
|
|
|
|
|
|
|
|
|
|
switch (param.second.type) {
|
|
|
|
|
case UsageParameter::Type::DIRECTION: {
|
|
|
|
|
|
|
|
|
|
auto visitor = compose(
|
|
|
|
|
[&](const EntityLocation& value) {},
|
|
|
|
|
[&](const WFMath::Point<3>& value) {},
|
|
|
|
|
[&](const WFMath::Vector<3>& value) {
|
|
|
|
|
is_valid = value.isValid();
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
boost::apply_visitor(visitor, arg);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case UsageParameter::Type::POSITION: {
|
|
|
|
|
auto visitor = compose(
|
|
|
|
|
[&](const EntityLocation& value) {},
|
|
|
|
|
[&](const WFMath::Point<3>& value) {
|
|
|
|
|
is_valid = value.isValid();
|
|
|
|
|
},
|
|
|
|
|
[&](const WFMath::Vector<3>& value) {}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
boost::apply_visitor(visitor, arg);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case UsageParameter::Type::ENTITY: {
|
|
|
|
|
|
|
|
|
|
auto visitor = compose(
|
|
|
|
|
[&](const EntityLocation& value) {
|
|
|
|
|
if (value.m_parent && !value.m_parent->isDestroyed()) {
|
|
|
|
|
if (param.second.constraint) {
|
|
|
|
|
EntityFilter::QueryContext queryContext{*value.m_parent, actor.get(), tool.get()};
|
|
|
|
|
queryContext.entity_lookup_fn = [](const std::string& id) { return BaseWorld::instance().getEntity(id); };
|
2018-10-15 22:06:53 +02:00
|
|
|
queryContext.type_lookup_fn = [](const std::string& id) { return Inheritance::instance().getType(id); };
|
2018-08-20 22:10:46 +02:00
|
|
|
is_valid = param.second.constraint->match(queryContext);
|
|
|
|
|
} else {
|
|
|
|
|
is_valid = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
[&](const WFMath::Point<3>& value) {},
|
|
|
|
|
[&](const WFMath::Vector<3>& value) {}
|
|
|
|
|
);
|
|
|
|
|
boost::apply_visitor(visitor, arg);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case UsageParameter::Type::ENTITYLOCATION: {
|
|
|
|
|
auto visitor = compose(
|
|
|
|
|
[&](const EntityLocation& value) {
|
|
|
|
|
if (value.isValid() && !value.m_parent->isDestroyed()) {
|
|
|
|
|
if (param.second.constraint) {
|
|
|
|
|
EntityFilter::QueryContext queryContext{*value.m_parent, actor.get(), tool.get()};
|
|
|
|
|
queryContext.entity_lookup_fn = [](const std::string& id) { return BaseWorld::instance().getEntity(id); };
|
2018-10-15 22:06:53 +02:00
|
|
|
queryContext.type_lookup_fn = [](const std::string& id) { return Inheritance::instance().getType(id); };
|
2018-08-20 22:10:46 +02:00
|
|
|
is_valid = param.second.constraint->match(queryContext);
|
|
|
|
|
} else {
|
|
|
|
|
is_valid = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
[&](const WFMath::Point<3>& value) {},
|
|
|
|
|
[&](const WFMath::Vector<3>& value) {}
|
|
|
|
|
);
|
|
|
|
|
boost::apply_visitor(visitor, arg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (is_valid) {
|
|
|
|
|
count++;
|
|
|
|
|
}
|
2018-07-31 22:43:41 +02:00
|
|
|
}
|
|
|
|
|
|
2018-08-20 22:10:46 +02:00
|
|
|
if (count < param.second.min) {
|
|
|
|
|
return {false, String::compose("Too few '%1' arguments. Should be minimum %2, got %3.", param.first, param.second.min, count)};
|
2018-07-31 22:43:41 +02:00
|
|
|
}
|
2018-08-20 22:10:46 +02:00
|
|
|
if (count > param.second.max) {
|
|
|
|
|
return {false, String::compose("Too many '%1' arguments. Should be maximum %2, got %3.", param.first, param.second.max, count)};
|
2018-07-31 22:43:41 +02:00
|
|
|
}
|
2018-08-20 22:10:46 +02:00
|
|
|
|
2018-07-31 22:43:41 +02:00
|
|
|
}
|
|
|
|
|
|
2018-08-20 22:10:46 +02:00
|
|
|
|
2018-07-31 22:43:41 +02:00
|
|
|
return {true, ""};
|
|
|
|
|
}
|