Skip to content

Commit

Permalink
Merge pull request #36 from sofa-framework/Prefab_addLinkParameter
Browse files Browse the repository at this point in the history
ADD: PrefabLinks
  • Loading branch information
marques-bruno authored Aug 18, 2020
2 parents 675191b + be31d20 commit b5c9cfb
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 26 deletions.
8 changes: 4 additions & 4 deletions Plugin/src/SofaPython3/DataHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,13 +541,12 @@ BaseData* addData(py::object py_self, const std::string& name, py::object value,
BaseData* data;

bool isSet = true;
if (value.is(py::none()))
if (value.is_none())
{
value = defaultValue;
isSet = false;
}


// create the data from the link passed as a string to the object
if (py::isinstance<py::str>(value) &&
!py::cast<std::string>(value).empty() &&
Expand All @@ -564,7 +563,7 @@ BaseData* addData(py::object py_self, const std::string& name, py::object value,
self->addData(data, name);
}
// create the data from another data (use as parent)
else if (py::isinstance<BaseData>(value) || py::isinstance<BaseData*>(value))
else if (!value.is_none() && (py::isinstance<BaseData>(value) || py::isinstance<BaseData*>(value)))
{
data = deriveTypeFromParent(py::cast<BaseData*>(value));
if (!data)
Expand All @@ -587,7 +586,8 @@ BaseData* addData(py::object py_self, const std::string& name, py::object value,
throw py::type_error(std::string("Invalid Type string: available types are\n") + typesString);
}
self->addData(data, name);
PythonFactory::fromPython(data, value);
if (!value.is_none())
PythonFactory::fromPython(data, value);
}
data->setName(name);
data->setGroup(group.c_str());
Expand Down
113 changes: 109 additions & 4 deletions Plugin/src/SofaPython3/DataHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ along with sofaqtquick. If not, see <http://www.gnu.org/licenses/>.
#include <sofa/core/sptr.h>
#include <sofa/helper/Factory.h>
#include <sofa/core/objectmodel/Data.h>
#include <sofa/core/objectmodel/Base.h>
#include <sofa/core/objectmodel/BaseObject.h>
#include <sofa/core/objectmodel/BaseNode.h>

#include "config.h"

Expand All @@ -44,10 +47,112 @@ namespace sofa {
}
namespace core {
namespace objectmodel {
class Base;
class BaseData;
class BaseNode;
class BaseObject;


class SOFAPYTHON3_API PrefabLink
{
public:
PrefabLink() {}
PrefabLink(const Base::SPtr& targetBase) { m_targetBase = targetBase; }
PrefabLink(BaseLink* targetLink) { m_targetBase = targetLink->getLinkedBase(); }
PrefabLink(const std::string& targetPath) { m_targetPath = targetPath; }

const Base::SPtr& getTargetBase() const { return m_targetBase; }
void setTargetBase(const Base::SPtr& targetBase) { m_targetBase = targetBase; }

const std::string& getTargetPath() const { return m_targetPath; }
void setTargetPath(const std::string& targetPath) { m_targetPath = targetPath; }

friend std::ostream& operator << ( std::ostream& out, const PrefabLink& l)
{
if (l.getTargetBase())
{
auto bn = l.getTargetBase()->toBaseNode();
auto bo = l.getTargetBase()->toBaseObject();
out << "@" + (bn ? bn->getPathName() : bo->getPathName());
}
out << l.getTargetPath();
return out;
}

friend std::istream& operator >> ( std::istream& in, PrefabLink& l)
{
std::string s;
in >> s;
l.setTargetPath(s);
return in;
}

private:
Base::SPtr m_targetBase { nullptr };
std::string m_targetPath {""};
};

class SOFAPYTHON3_API DataLink : public Data<PrefabLink>
{
typedef Data<PrefabLink> Inherit;

DataLink( const std::string& helpMsg="", bool isDisplayed=true, bool isReadOnly=false )
: Inherit(helpMsg, isDisplayed, isReadOnly)
{
}

DataLink( const std::string& value, const std::string& helpMsg="", bool isDisplayed=true, bool isReadOnly=false )
: Inherit(value, helpMsg, isDisplayed, isReadOnly)
{
}

explicit DataLink(const BaseData::BaseInitData& init)
: Inherit(init)
{
}

const PrefabLink& getValue() const
{
updateIfDirty();
if (m_value.getValue().getTargetBase()) return m_value.getValue();

auto self = const_cast<DataLink*>(this);

Base* dst = nullptr;
this->getOwner()->findLinkDest(dst, self->m_value.getValue().getTargetPath(), nullptr);
if (dst) {
auto edit = self->m_value.beginEdit();
edit->setTargetBase(dst);
edit->setTargetPath("");
self->m_value.endEdit();
}
return m_value.getValue();
}

std::string getValueString() const
{
const auto& ptr = getValue();
if (ptr.getTargetBase())
{
auto bn = ptr.getTargetBase()->toBaseNode();
auto bo = ptr.getTargetBase()->toBaseObject();
return "@" + (bn ? bn->getPathName() : bo->getPathName());
}
return ptr.getTargetPath();
}


bool read(const std::string& value)
{
Base* dst;
auto data = m_value.beginEdit();
if (this->getOwner()->findLinkDest(dst, value, nullptr) && dst != nullptr)
data->setTargetBase(dst);
else {
data->setTargetBase(nullptr);
data->setTargetPath(value);
}
return true;
}
};

}
}
}
Expand Down Expand Up @@ -189,7 +294,7 @@ class scoped_writeonly_access
~scoped_writeonly_access(){ data->endEditVoidPtr(); }
};

SOFAPYTHON3_API BaseData* addData(py::object py_self, const std::string& name, py::object value = py::object(), py::object defaultValue = py::object(), const std::string& help = "", const std::string& group = "Property", std::string type = "");
SOFAPYTHON3_API BaseData* addData(py::object py_self, const std::string& name, py::object value = py::none(), py::object defaultValue = py::none(), const std::string& help = "", const std::string& group = "Property", std::string type = "");
SOFAPYTHON3_API BaseLink* addLink(py::object py_self, const std::string& name, py::object value, const std::string& help);
SOFAPYTHON3_API bool isProtectedKeyword(const std::string& name);

Expand Down
19 changes: 6 additions & 13 deletions Plugin/src/SofaPython3/Prefab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ using sofa::core::objectmodel::Event;

void Prefab::init()
{
std::cout << "prefab::init" << std::endl;
reinit();
Inherit1::init(sofa::core::ExecParams::defaultInstance());
m_is_initialized = true;
}

void PrefabFileEventListener::fileHasChanged(const std::string &filename)
Expand All @@ -44,18 +44,15 @@ void PrefabFileEventListener::fileHasChanged(const std::string &filename)

void Prefab::reinit()
{
std::cout << "prefab::reinit" << std::endl;
clearLoggedMessages();

/// remove everything in the node.
execute<sofa::simulation::DeleteVisitor>(sofa::core::ExecParams::defaultInstance());
std::cout << "prefab::doReInit" << std::endl;

doReInit();

std::cout << "simulation->initNode" << std::endl;
/// Beurk beurk beurk
sofa::simulation::getSimulation()->initNode(this);
std::cout << "VisualInitVisitor" << std::endl;
execute<VisualInitVisitor>(nullptr);

d_componentState.setValue(sofa::core::objectmodel::ComponentState::Valid);
Expand All @@ -78,27 +75,23 @@ Prefab::~Prefab()
}


void Prefab::addPrefabParameter(const std::string& name, py::object value, const std::string& help, std::string type)
void Prefab::addPrefabParameter(const std::string& name, const std::string& help, const std::string& type, py::object defaultValue)
{
sofa::core::objectmodel::BaseData* data = findData(name);
if(data == nullptr)
if(!findData(name) && !findLink(name))
{
sofa::core::objectmodel::BaseData* data = sofapython3::addData(py::cast(this), name, value, py::object(), help, "Prefab's properties", type);
sofa::core::objectmodel::BaseData* data = sofapython3::addData(py::cast(this), name, py::none(), defaultValue, help, "Prefab's properties", type);
data->setRequired(true);
m_datacallback.addInputs({data});
return;
}
//PythonFactory::fromPython(data, value);
}

void Prefab::setSourceTracking(const std::string& filename)
{
std::cout << "Activating source tracking to " << filename << std::endl;
FileMonitor::addFile(filename, &m_filelistener);
}

void Prefab::breakPrefab()
{
std::cout << "Breaking prefab" << std::endl;
FileMonitor::removeListener(&m_filelistener);
for (auto& data : this->getDataFields())
if (data->getGroup() == "Prefab's properties")
Expand Down
3 changes: 2 additions & 1 deletion Plugin/src/SofaPython3/Prefab.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class SOFAPYTHON3_API Prefab : public BasePrefab
void reinit();
virtual void doReInit() ;

void addPrefabParameter(const std::string& name, pybind11::object value, const std::string& help, std::string type);
void addPrefabParameter(const std::string& name, const std::string& help, const std::string& type, pybind11::object defaultValue = py::none());
void setSourceTracking(const std::string& filename);
void breakPrefab();

Expand All @@ -48,5 +48,6 @@ class SOFAPYTHON3_API Prefab : public BasePrefab

PrefabFileEventListener m_filelistener;
DataCallback m_datacallback;
bool m_is_initialized {false};
};
} // namespace sofapython3
4 changes: 4 additions & 0 deletions Plugin/src/SofaPython3/PythonFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ bool PythonFactory::registerDefaultTypes()
// helper vector style containers
std::string containers[] = {"vector"};

// PrefabLink
PythonFactory::registerType<sofa::core::objectmodel::PrefabLink>("PrefabLink");
PythonFactory::registerType<sofa::core::objectmodel::PrefabLink>("Link");

// Scalars
PythonFactory::registerType<std::string>("string");
PythonFactory::registerType<float>("float");
Expand Down
11 changes: 8 additions & 3 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Prefab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,17 @@ class Prefab_Trampoline : public Prefab, public PythonTrampoline

void Prefab_Trampoline::doReInit()
{
if (!m_is_initialized) {
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Loading);
msg_warning(this) << "Prefab instantiated. Check for required prefab parameters to fully populate";
return;
}
try{
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Valid);
PYBIND11_OVERLOAD(void, Prefab, doReInit, );
} catch (std::exception& e)
{
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
msg_error(this) << e.what();
}
}
Expand All @@ -98,8 +105,6 @@ void moduleAddPrefab(py::module &m) {
std::string key = py::cast<std::string>(kv.first);
py::object value = py::reinterpret_borrow<py::object>(kv.second);

std::cout << "PREFAB ARE BROKEN " << key << std::endl;

if( key == "name")
c->setName(py::cast<std::string>(kv.second));
try {
Expand All @@ -117,7 +122,7 @@ void moduleAddPrefab(py::module &m) {

f.def("setSourceTracking", &Prefab::setSourceTracking);
f.def("addPrefabParameter", &Prefab::addPrefabParameter,
"name"_a, "value"_a, "help"_a, "type"_a);
"name"_a, "help"_a, "type"_a, "default"_a = py::none());
f.def("init", &Prefab::init);
f.def("reinit", &Prefab::reinit);
}
Expand Down
4 changes: 3 additions & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataContainer.h
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataContainer_doc.h
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataString.h
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataLink.h
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataString_doc.h
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataVectorString.h
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataVectorString_doc.h
Expand All @@ -52,6 +53,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DataEngine.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataContainer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataString.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataLink.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataVectorString.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_ForceField.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Visitor.cpp
Expand Down Expand Up @@ -79,4 +81,4 @@ SP3_add_python_module(
SOURCES ${SOURCE_FILES}
HEADERS ${HEADER_FILES}
DEPENDS SofaCore SofaSimulationCore SofaSimulationGraph SofaBaseVisual SofaPython3::Plugin
)
)
60 changes: 60 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Data/Binding_DataLink.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "Binding_DataLink.h"

#include <sofa/core/objectmodel/BaseData.h>
using sofa::core::objectmodel::BaseData;


#include <SofaPython3/DataHelper.h>
using sofa::core::objectmodel::PrefabLink;
#include <SofaPython3/PythonFactory.h>

namespace sofapython3
{

py::str getTargetPath(PrefabLink& link)
{
return link.getTargetPath();
}

py::object getTargetBase(PrefabLink& link)
{
auto base = link.getTargetBase().get();
if (base)
return PythonFactory::toPython(base);
return py::none();
}

py::str DataLink::__str__()
{
std::stringstream s;
s << "Sofa.Core.DataLink<name='" << getName()
<< "', value='" << getValueString()
<< "', address='"<< (void*)this <<"'>";
return s.str();
}

py::str DataLink::__repr__()
{
return py::repr(convertToPython(this));
}

void moduleAddDataLink(py::module &m)
{
py::class_<PrefabLink, std::unique_ptr<PrefabLink, py::nodelete>> l(m, "PrefabLink");
l.def(py::init<const Base::SPtr&>());
l.def(py::init<BaseLink*>());
l.def(py::init<const std::string&>());
l.def("getTargetBase", &getTargetBase);
l.def("getTargetPath", &getTargetPath);

py::class_<DataLink, BaseData, std::unique_ptr<DataLink, py::nodelete>> d(m, "DataLink");

PythonFactory::registerType("DataLink", [](BaseData* data) -> py::object {
return py::cast(reinterpret_cast<DataLink*>(data));
});

d.def("__repr__",&DataLink::__repr__);
d.def("__str__", &DataLink::__str__);
}

} // namespace sofapython3
Loading

0 comments on commit b5c9cfb

Please sign in to comment.