Skip to content

Commit

Permalink
Merge pull request #394 from gergondet/topic/ImprovedForms
Browse files Browse the repository at this point in the history
  • Loading branch information
gergondet authored Sep 13, 2023
2 parents c7274c9 + 24f39d6 commit ecc5a08
Show file tree
Hide file tree
Showing 12 changed files with 762 additions and 171 deletions.
153 changes: 152 additions & 1 deletion include/mc_control/ControllerClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,10 @@ struct MC_CONTROL_CLIENT_DLLAPI ControllerClient
{
}

/** An array input within a form */
/** An array input within a form
*
* This is kept for backward compatibility, mc_rtc never calls this version and you should implement the full version
*/
virtual void form_array_input(const ElementId & formId,
const std::string & name,
bool required,
Expand All @@ -585,6 +588,18 @@ struct MC_CONTROL_CLIENT_DLLAPI ControllerClient
form_array_input(formId, name, required, default_, fixed_size);
}

/** An array input within a form */
virtual void form_array_input(const ElementId & formId,
const std::string & name,
bool required,
const std::vector<std::string> & /*labels*/,
const Eigen::VectorXd & default_,
bool fixed_size,
bool default_from_user)
{
form_array_input(formId, name, required, default_, fixed_size, default_from_user);
}

/** A combo input within a form
*
* This is kept for backward compatibility, mc_rtc never calls this version and you should implement the full version
Expand Down Expand Up @@ -643,6 +658,142 @@ struct MC_CONTROL_CLIENT_DLLAPI ControllerClient
{
}

/** A 3D point that can be edited within a Form
*
* \p formId Identifier of the form
*
* \p name Name of the entry
*
* \p required If true, it must hold a value when the form is sent
*
* \p default_ Default value in the form
*
* \p default_from_user Default is provided by the user
*
* \p interactive Should display an interactive marker
*/
virtual void form_point3d_input(const ElementId & /*formId*/,
const std::string & /*name*/,
bool /*required*/,
const Eigen::Vector3d & /*default_*/,
bool /*default_from_user*/,
bool /*interactive*/)
{
}

/** A rotation that can be edited within a Form
*
* Note: this requires a PTransformd to place the rotation in space but only the rotation should be provided in the
* callback
*
* \p formId Identifier of the form
*
* \p name Name of the entry
*
* \p required If true, it must hold a value when the form is sent
*
* \p default_ Default value in the form
*
* \p default_from_user Default is provided by the user
*
* \p interactive Should display an interactive marker
*/
virtual void form_rotation_input(const ElementId & /*formId*/,
const std::string & /*name*/,
bool /*required*/,
const sva::PTransformd & /*default_*/,
bool /*default_from_user*/,
bool /*interactive*/)
{
}

/** A transform that can be edited within a Form
*
* \p formId Identifier of the form
*
* \p name Name of the entry
*
* \p required If true, it must hold a value when the form is sent
*
* \p default_ Default value in the form
*
* \p default_from_user Default is provided by the user
*
* \p interactive Should display an interactive marker
*/
virtual void form_transform_input(const ElementId & /*formId*/,
const std::string & /*name*/,
bool /*required*/,
const sva::PTransformd & /*default_*/,
bool /*default_from_user*/,
bool /*interactive*/)
{
}

/** Starts a form within a form
*
* After this call, all calls related to form elements must be interpreted as belonging to this sub-form
*
* \p name Name of the object
*
* \p required If true, it must hold a value when the form is sent
*/
virtual void start_form_object_input(const std::string & /*name*/, bool /*required*/) {}

/** Pendant to \ref start_form_object_input
*
* After this call, all calls related to form elements must be interpreted as belonging to the form's parent
*
*/
virtual void end_form_object_input() {}

/** Starts a generic array input
*
* The next call related to form elements must be interpreted as describing the type of members the array expects
*
* \p name Name of the array this generates
*
* \p required If true, it must hold a value (can be an empty array) when the form is sent
*
* \p data Existing data in the array, must be sent along with the form if provided
*/
virtual void start_form_generic_array_input(const std::string & /*name*/,
bool /*required*/,
std::optional<std::vector<Configuration>> /*data*/)
{
}

/** Pendant to \ref start_form_generic_array_input
*
* After this call, all calls related to form elements must be interpreted as belonging to the form's parent
*
*/
virtual void end_form_generic_array_input() {}

/** Start a one-of input within a form
*
* After this call, each call related to form elements is one option offered by the one-of selector. The name of the
* element should be used to distinguish the selected type
*
* \p name Name of the one-of selection
*
* \p required If true, it must hold a valid value when sent
*
* \p data Active data
*/
virtual void start_form_one_of_input(const std::string & /*name*/,
bool /*required*/,
const std::optional<std::pair<size_t, Configuration>> & /*data*/)
{
}

/** Pendant to \ref start_form_one_of_input
*
* After this call, all calls related to form elements must be interpreted as belonging to the form's parent
*
*/
virtual void end_form_one_of_input() {}

/** Called when new plot data arrives
*
* This should open a new plotting window with the provided title.
Expand Down
20 changes: 6 additions & 14 deletions include/mc_rtc/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -1481,9 +1481,9 @@ struct MC_RTC_UTILS_DLLAPI Configuration

/*! \brief Add a variant object into the JSON document
*
* The variant is written as [value.index(), std::get<value.index()>(value)] if it holds a value
* The variant is written as [value.index(), std::get<value.index()>(value)]
*
* Otherwise it is written as [std::variant_npos, std::variant_npos]
* \throws If the variant is in valueless state
*
* \param key Key of the element
*
Expand All @@ -1494,11 +1494,7 @@ struct MC_RTC_UTILS_DLLAPI Configuration
{
Configuration v = array(key, 2);
v.push(value.index());
if(value.index() != std::variant_npos)
{
std::visit([&v](const auto & hold) { v.push(hold); }, value);
}
else { v.push(value.index()); }
std::visit([&v](const auto & hold) { v.push(hold); }, value);
}

/** Integral type conversions
Expand Down Expand Up @@ -1628,9 +1624,9 @@ struct MC_RTC_UTILS_DLLAPI Configuration

/*! \brief Push a variant object into the JSON document
*
* The variant is written as [value.index(), std::get<value.index()>(value)] if it holds a value
* The variant is written as [value.index(), std::get<value.index()>(value)]
*
* Otherwise it is written as [std::variant_npos, std::variant_npos]
* \throws If the variant is in valueless state
*
* \param key Key of the element
*
Expand All @@ -1641,11 +1637,7 @@ struct MC_RTC_UTILS_DLLAPI Configuration
{
Configuration v = array(2);
v.push(value.index());
if(value.index() != std::variant_npos)
{
std::visit([&v](const auto & hold) { v.push(hold); }, value);
}
else { v.push(value.index()); }
std::visit([&v](const auto & hold) { v.push(hold); }, value);
}

/** Remove a given element
Expand Down
52 changes: 42 additions & 10 deletions include/mc_rtc/MessagePackBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
#include <set>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>

namespace mc_rtc
{

struct Configuration;

struct MessagePackBuilder;
struct MessagePackBuilderImpl;

namespace internal
Expand Down Expand Up @@ -61,6 +62,20 @@ constexpr bool is_like_uint32_t = is_like<uint32_t, T>();
template<typename T>
constexpr bool is_like_uint64_t = is_like<uint64_t, T>();

template<typename T, typename = void>
struct has_write_builder : std::false_type
{
};

template<typename T>
struct has_write_builder<T, std::void_t<decltype(std::declval<const T &>().write(std::declval<MessagePackBuilder &>()))>>
: std::true_type
{
};

template<typename T>
static inline constexpr bool has_write_builder_v = has_write_builder<T>::value;

} // namespace internal

/** Helper class to build a MessagePack message
Expand Down Expand Up @@ -133,31 +148,31 @@ struct MC_RTC_UTILS_DLLAPI MessagePackBuilder

/** Write an Eigen::Vector2d
*
* Serializes as an array of size 2
* Serialized as an array of size 2
*/
void write(const Eigen::Vector2d & v);

/** Write an Eigen::Vector3d
*
* Serializes as an array of size 3
* Serialized as an array of size 3
*/
void write(const Eigen::Vector3d & v);

/** Write an Eigen::Vector4d
*
* Serializes as an array of size 4
* Serialized as an array of size 4
*/
void write(const Eigen::Vector4d & v);

/** Write an Eigen::Vector6d
*
* Serializes as an array of size 6
* Serialized as an array of size 6
*/
void write(const Eigen::Vector6d & v);

/** Write an Eigen::VectorXd
*
* Serializes as an array of size X
* Serialized as an array of size X
*/
void write(const Eigen::VectorXd & v);

Expand All @@ -172,19 +187,19 @@ struct MC_RTC_UTILS_DLLAPI MessagePackBuilder

/** Write an Eigen::Quaterniond
*
* Serializes as an array of size X
* Serialized as an array of size 4
*/
void write(const Eigen::Quaterniond & q);

/** Write an Eigen::Matrix3d
*
* Serializes as an array of size 9
* Serialized as an array of size 9
*/
void write(const Eigen::Matrix3d & m);

/** Write an sva::PTransformd
*
* Serializes as an array of size 12 (Matrix3d + Vector3d)
* Serialized as an array of size 12 (Matrix3d + Vector3d)
*/
void write(const sva::PTransformd & pt);

Expand All @@ -208,7 +223,7 @@ struct MC_RTC_UTILS_DLLAPI MessagePackBuilder

/** Write an mc_rtc::Configuration
*
* Serialied as the JSON data it holds
* Serialized as the JSON data it holds
*/
void write(const mc_rtc::Configuration & config);

Expand All @@ -227,6 +242,13 @@ struct MC_RTC_UTILS_DLLAPI MessagePackBuilder
else { static_assert(!std::is_same_v<T, T>, "T is integral but has an unsupported size"); }
}

/** Write \tparam T to MessagePack if T implements T::write(MessagePackBuilder &) const */
template<typename T, typename = std::enable_if_t<internal::has_write_builder_v<T>>>
void write(const T & value)
{
value.write(*this);
}

/** @} */
/* End Add data to the MessagePack section (advanced) */

Expand Down Expand Up @@ -297,6 +319,16 @@ struct MC_RTC_UTILS_DLLAPI MessagePackBuilder
finish_array();
}

/** Write an std::variant<Args...> */
template<typename... Args>
void write(const std::variant<Args...> & value)
{
start_array(2);
write(value.index());
std::visit([this](const auto & v) { write(v); }, value);
finish_array();
}

/** Write an Eigen::Ref */
template<typename Type, int Options, typename StrideType>
void write(const Eigen::Ref<Type, Options, StrideType> & v)
Expand Down
Loading

0 comments on commit ecc5a08

Please sign in to comment.