/* 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. */ #include #include #include #include #include "CyPy_LocatedEntity.h" #include "CyPy_Props.h" #include "common/TypeNode.h" #include "common/Inheritance.h" Py::PythonClassObject wrapLocatedEntity(LocatedEntity* le) { return CyPy_LocatedEntity::wrap(le); } CyPy_LocatedEntity::CyPy_LocatedEntity(Py::PythonClassInstance* self, Py::Tuple& args, Py::Dict& kwds) : PythonClass(self, args, kwds) { args.verify_length(1); auto arg = args.front(); auto id = arg.str().as_string(); long intId = integerId(id); if (intId == -1L) { throw Py::TypeError("LocatedEntity() requires string/int ID"); } // m_value = new Entity(id, intId); } CyPy_LocatedEntity::CyPy_LocatedEntity(Py::PythonClassInstance* self, LocatedEntity* value) : PythonClass(self), m_value(value) { m_value->incRef(); } CyPy_LocatedEntity::~CyPy_LocatedEntity() { m_value->decRef(); } void CyPy_LocatedEntity::init_type() { behaviors().name("LocatedEntity"); behaviors().doc(""); behaviors().supportRichCompare(); behaviors().readyType(); } LocatedEntity& CyPy_LocatedEntity::value(const Py::Object& object) { return *Py::PythonClassObject(object).getCxxObject()->m_value; } Py::Object CyPy_LocatedEntity::getattro(const Py::String& name) { auto nameStr = name.as_string(); if (nameStr == "id") { return Py::String(m_value->getId()); } if (nameStr == "props") { Py::Callable class_type(CyPy_Props::type()); Py::PythonClassObject propsObj(class_type.apply()); propsObj.getCxxObject()->m_value = m_value; return propsObj; } if (nameStr == "type") { if (!m_value->getType()) { throw Py::AttributeError(name); } return Py::String(m_value->getType()->name()); } //TODO: move to CyPy_BaseMind // if (nameStr == "time") { // PyWorldTime * worldtime = newPyWorldTime(); // if (worldtime != nullptr) { // worldtime->time = m_value->getTime(); // } // return Py::Object((PyObject *)worldtime); // } if (nameStr == "location") { PyLocation* loc = newPyLocation(); if (loc != nullptr) { loc->location = &m_value->m_location; loc->owner = m_value; } return Py::Object((PyObject*) loc); } if (nameStr == "contains") { if (!m_value->m_contains) { return Py::None(); } Py::List list; for (auto& child : *m_value->m_contains) { list.append(wrapLocatedEntity(child)); } return list; } if (nameStr == "visible") { return Py::Boolean(m_value->isVisible()); } return PythonExtensionBase::getattro(name); } int CyPy_LocatedEntity::setattro(const Py::String& name, const Py::Object& attr) { auto nameStr = name.as_string(); //FIXME: perhaps in BaseMind instead? if (nameStr == "map") { throw Py::AttributeError("map attribute forbidden"); } if (nameStr == "type") { if (m_value->getType()) { throw Py::RuntimeError("Cannot mutate entity type"); } const TypeNode* type = Inheritance::instance().getType(attr.str().as_string()); if (!type) { throw Py::ValueError("Entity type unknown"); } m_value->setType(type); return 0; } return PythonExtensionBase::setattro(name, attr); } Py::Object CyPy_LocatedEntity::rich_compare(const Py::Object& other, int op) { if (other.isType(CyPy_LocatedEntity::type())) { Py::PythonClassObject otherObj(other); if (m_value == nullptr || otherObj.getCxxObject()->m_value == nullptr) { return Py::False(); } if (op == Py_EQ) { return (m_value == otherObj.getCxxObject()->m_value) ? Py::True() : Py::False(); } else if (op == Py_NE) { return (m_value != otherObj.getCxxObject()->m_value) ? Py::True() : Py::False(); } } else { if (op == Py_EQ) { return Py::False(); } else if (op == Py_NE) { return Py::True(); } } throw Py::NotImplementedError(); } Py::PythonClassObject CyPy_LocatedEntity::wrap(LocatedEntity* value) { if (!value->m_scriptEntity.empty()) { return boost::any_cast>(value->m_scriptEntity); } else { auto obj = CyPy_LocatedEntity::extension_object_new(CyPy_LocatedEntity::type_object(), nullptr, nullptr); new CyPy_LocatedEntity(reinterpret_cast(obj), value); Py::PythonClassObject wrapper(obj); value->m_scriptEntity = boost::any(wrapper); return wrapper; } // auto obj = (CyPy_LocatedEntity*)extension_object_new(type_object(), nullptr, nullptr); // obj->m_value = entity; // return Py::PythonClassObject(obj); // auto obj = (Py::PythonClassInstance*)extension_object_new(type_object(), nullptr, nullptr); // obj->m_pycxx_object = new CyPy_LocatedEntity(obj, entity); // return Py::PythonClassObject(obj); }