Commit aa8aa45e authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

gui: adds automatic reorder graph

parent 4830b289
This diff is collapsed.
......@@ -10,7 +10,6 @@
#include <filesystem>
#include <fstream>
#include <thread>
#include <unordered_map>
#include <variant>
#include <vector>
......@@ -19,6 +18,22 @@
namespace irt {
template<class C>
constexpr int
length(const C& c) noexcept
{
return static_cast<int>(c.size());
}
template<class T, size_t N>
constexpr int
length(const T (&array)[N]) noexcept
{
(void)array;
return static_cast<int>(N);
}
template<typename Identifier>
constexpr Identifier
undefined() noexcept
......@@ -47,50 +62,59 @@ static inline constexpr int not_found = -1;
struct top_cluster
{
std::vector<child_id> children;
std::vector<int> nodes;
std::vector<std::pair<child_id, int>> children;
int next_node_id = 0;
static inline constexpr int not_found = -1;
status init(size_t models) noexcept
{
try {
children.reserve(models);
} catch (const std::bad_alloc&) {
std::vector<std::pair<child_id, int>>().swap(children);
irt_bad_return(status::gui_not_enough_memory);
}
return status::success;
}
int get_index(const child_id id) const noexcept
{
auto it = std::find(std::begin(children), std::end(children), id);
if (it == std::end(children))
return not_found;
for (int i = 0, e = length(children); i != e; ++i)
if (children[i].first == id)
return i;
return static_cast<int>(std::distance(std::begin(children), it));
return not_found;
}
int get_index(const int node) const noexcept
{
auto it = std::find(std::begin(nodes), std::end(nodes), node);
if (it == std::end(nodes))
return not_found;
for (int i = 0, e = length(children); i != e; ++i)
if (children[i].second == node)
return i;
return static_cast<int>(std::distance(std::begin(nodes), it));
return not_found;
}
void clear() noexcept
{
children.clear();
nodes.clear();
}
void pop(const int index) noexcept
{
std::swap(children[index], children.back());
children.pop_back();
std::swap(nodes[index], nodes.back());
nodes.pop_back();
}
void emplace_back(const child_id id)
int emplace_back(const child_id id)
{
children.emplace_back(id);
nodes.emplace_back(next_node_id);
++next_node_id;
int ret = next_node_id++;
children.emplace_back(id, ret);
return ret;
}
};
......@@ -180,11 +204,13 @@ struct editor
array<cluster_id> clusters_mapper; /* group per cluster_id */
array<cluster_id> models_mapper; /* group per model_id */
ImVector<ImVec2> positions;
ImVector<ImVec2> displacements;
top_cluster top;
status initialize(u32 id) noexcept;
void clear() noexcept;
void reorder() noexcept;
void group(const ImVector<int>& nodes) noexcept;
void ungroup(const int node) noexcept;
......@@ -192,9 +218,12 @@ struct editor
void free_children(const ImVector<int>& nodes) noexcept;
status copy(const ImVector<int>& nodes) noexcept;
void reorder_subgroup(const size_t from,
const size_t length,
ImVec2 click_pos) noexcept;
void reorder() noexcept;
bool is_in_hierarchy(const cluster& group,
const cluster_id group_to_search) const noexcept;
cluster_id ancestor(const child_id child) const noexcept;
int get_top_group_ref(const child_id child) const noexcept;
cluster_id parent(cluster_id child) const noexcept
{
......@@ -216,7 +245,7 @@ struct editor
models_mapper[get_index(child)] = parent;
}
int get_in(input_port_id id) const noexcept
static int get_in(input_port_id id) noexcept
{
return static_cast<int>(get_index(id));
}
......@@ -228,7 +257,7 @@ struct editor
return port ? sim.input_ports.get_id(port) : undefined<input_port_id>();
}
int get_out(output_port_id id) const noexcept
static int get_out(output_port_id id) noexcept
{
constexpr u32 is_output = 1 << 31;
u32 index = get_index(id);
......@@ -261,4 +290,4 @@ struct editor
} // namespace irt
#endif
\ No newline at end of file
#endif
......@@ -4390,25 +4390,24 @@ struct simulation
{
return dispatch(
mdl.type,
[ dyn_id = mdl.id, port,
index ]<typename DynamicsM>(DynamicsM & dyn_models)
->status {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_output_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
for (size_t i = 0, e = std::size(dyn->y); i != e; ++i) {
if (dyn->y[i] == port) {
*index = static_cast<int>(i);
return status::success;
}
}
}
return status::dynamics_unknown_port_id;
});
[dyn_id = mdl.id, port, index]<typename DynamicsM>(
DynamicsM& dyn_models) -> status {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_output_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
for (size_t i = 0, e = std::size(dyn->y); i != e; ++i) {
if (dyn->y[i] == port) {
*index = static_cast<int>(i);
return status::success;
}
}
}
return status::dynamics_unknown_port_id;
});
}
template<typename Function>
......@@ -4416,20 +4415,19 @@ struct simulation
{
dispatch(
mdl.type,
[ this, &f, dyn_id = mdl.id ]<typename DynamicsM>(DynamicsM &
dyn_models)
{
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_input_port_t, Dynamics>) {
if (auto* dyn = dyn_models.try_to_get(dyn_id); dyn)
for (size_t i = 0, e = std::size(dyn->x); i != e; ++i)
if (auto* port = input_ports.try_to_get(dyn->x[i]);
port)
f(*port);
}
return status::success;
});
[this, &f, dyn_id = mdl.id]<typename DynamicsM>(
DynamicsM& dyn_models) {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_input_port_t, Dynamics>) {
if (auto* dyn = dyn_models.try_to_get(dyn_id); dyn)
for (size_t i = 0, e = std::size(dyn->x); i != e; ++i)
if (auto* port = input_ports.try_to_get(dyn->x[i]);
port)
f(*port, dyn->x[i]);
}
return status::success;
});
}
template<typename Function>
......@@ -4437,20 +4435,20 @@ struct simulation
{
dispatch(
mdl.type,
[ this, &f, dyn_id = mdl.id ]<typename DynamicsM>(DynamicsM &
dyn_models) {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_output_port_t, Dynamics>) {
if (auto* dyn = dyn_models.try_to_get(dyn_id); dyn)
for (size_t i = 0, e = std::size(dyn->y); i != e; ++i)
if (auto* port = output_ports.try_to_get(dyn->y[i]);
port)
f(*port);
}
return status::success;
});
[this, &f, dyn_id = mdl.id]<typename DynamicsM>(
DynamicsM& dyn_models) {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_output_port_t, Dynamics>) {
if (auto* dyn = dyn_models.try_to_get(dyn_id); dyn)
for (size_t i = 0, e = std::size(dyn->y); i != e; ++i)
if (auto* port = output_ports.try_to_get(dyn->y[i]);
port)
f(*port, dyn->y[i]);
}
return status::success;
});
}
status get_input_port_index(const model& mdl,
......@@ -4459,25 +4457,24 @@ struct simulation
{
return dispatch(
mdl.type,
[ dyn_id = mdl.id, port,
index ]<typename DynamicsM>(DynamicsM & dyn_models)
->status {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_input_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
for (size_t i = 0, e = std::size(dyn->x); i != e; ++i) {
if (dyn->x[i] == port) {
*index = static_cast<int>(i);
return status::success;
}
}
}
return status::dynamics_unknown_port_id;
});
[dyn_id = mdl.id, port, index]<typename DynamicsM>(
DynamicsM& dyn_models) -> status {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_input_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
for (size_t i = 0, e = std::size(dyn->x); i != e; ++i) {
if (dyn->x[i] == port) {
*index = static_cast<int>(i);
return status::success;
}
}
}
return status::dynamics_unknown_port_id;
});
}
status get_output_port_id(const model& mdl,
......@@ -4486,26 +4483,24 @@ struct simulation
{
return dispatch(
mdl.type,
[ dyn_id = mdl.id, index,
port ]<typename DynamicsM>(DynamicsM & dyn_models)
->status {
using Dynamics = typename DynamicsM::value_type;
[dyn_id = mdl.id, index, port]<typename DynamicsM>(
DynamicsM& dyn_models) -> status {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_output_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
if constexpr (is_detected_v<has_output_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
irt_return_if_fail(0 <= index &&
static_cast<size_t>(index) <
std::size(dyn->y),
status::dynamics_unknown_port_id);
irt_return_if_fail(0 <= index && static_cast<size_t>(index) <
std::size(dyn->y),
status::dynamics_unknown_port_id);
*port = dyn->y[index];
return status::success;
}
*port = dyn->y[index];
return status::success;
}
return status::dynamics_unknown_port_id;
});
return status::dynamics_unknown_port_id;
});
}
status get_input_port_id(const model& mdl,
......@@ -4514,26 +4509,24 @@ struct simulation
{
return dispatch(
mdl.type,
[ dyn_id = mdl.id, index,
port ]<typename DynamicsM>(DynamicsM & dyn_models)
->status {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_input_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
irt_return_if_fail(0 <= index &&
static_cast<size_t>(index) <
std::size(dyn->x),
status::dynamics_unknown_port_id);
*port = dyn->x[index];
return status::success;
}
[dyn_id = mdl.id, index, port]<typename DynamicsM>(
DynamicsM& dyn_models) -> status {
using Dynamics = typename DynamicsM::value_type;
if constexpr (is_detected_v<has_input_port_t, Dynamics>) {
auto* dyn = dyn_models.try_to_get(dyn_id);
irt_return_if_fail(dyn, status::dynamics_unknown_id);
irt_return_if_fail(0 <= index && static_cast<size_t>(index) <
std::size(dyn->x),
status::dynamics_unknown_port_id);
*port = dyn->x[index];
return status::success;
}
return status::dynamics_unknown_port_id;
});
return status::dynamics_unknown_port_id;
});
}
template<typename Iterator>
......@@ -4628,37 +4621,36 @@ public:
auto ret = dispatch(
mdl->type,
[ this, &mdl,
copy ]<typename DynamicsM>(DynamicsM & dynamics_models)
->status {
using Dynamics = typename DynamicsM::value_type;
[this, &mdl, copy]<typename DynamicsM>(
DynamicsM& dynamics_models) -> status {
using Dynamics = typename DynamicsM::value_type;
irt_return_if_fail(dynamics_models.can_alloc(1),
status::dynamics_not_enough_memory);
irt_return_if_fail(dynamics_models.can_alloc(1),
status::dynamics_not_enough_memory);
auto* dyn_ptr = dynamics_models.try_to_get(mdl->id);
irt_return_if_fail(dyn_ptr, status::dynamics_unknown_id);
auto* dyn_ptr = dynamics_models.try_to_get(mdl->id);
irt_return_if_fail(dyn_ptr, status::dynamics_unknown_id);
auto& new_dyn = dynamics_models.alloc(*dyn_ptr);
auto new_dyn_id = dynamics_models.get_id(new_dyn);
auto& new_dyn = dynamics_models.alloc(*dyn_ptr);
auto new_dyn_id = dynamics_models.get_id(new_dyn);
if constexpr (is_detected_v<has_input_port_t, Dynamics>)
std::fill_n(new_dyn.x,
std::size(new_dyn.x),
static_cast<input_port_id>(0));
if constexpr (is_detected_v<has_input_port_t, Dynamics>)
std::fill_n(new_dyn.x,
std::size(new_dyn.x),
static_cast<input_port_id>(0));
if constexpr (is_detected_v<has_output_port_t, Dynamics>)
std::fill_n(new_dyn.y,
std::size(new_dyn.y),
static_cast<output_port_id>(0));
if constexpr (is_detected_v<has_output_port_t, Dynamics>)
std::fill_n(new_dyn.y,
std::size(new_dyn.y),
static_cast<output_port_id>(0));
irt_return_if_bad(
this->alloc(new_dyn, new_dyn_id, mdl->name.c_str()));
irt_return_if_bad(
this->alloc(new_dyn, new_dyn_id, mdl->name.c_str()));
*copy = new_dyn.id;
*copy = new_dyn.id;
return status::success;
});
return status::success;
});
irt_return_if_bad(ret);
}
......@@ -4670,8 +4662,8 @@ public:
auto ret = dispatch(
mdl->type,
[ this, model_it, first, last,
out ]<typename DynamicsM>(DynamicsM & dynamics_models) {
[this, model_it, first, last, out]<typename DynamicsM>(
DynamicsM& dynamics_models) {
using Dynamics = typename DynamicsM::value_type;
auto* mdl_src = this->models.try_to_get(*(first + model_it));
......@@ -5162,8 +5154,7 @@ public:
{
return dispatch(
mdl.type,
[ this, &mdl,
t ]<typename DynamicsModels>(DynamicsModels & dyn_models) {
[this, &mdl, t]<typename DynamicsModels>(DynamicsModels& dyn_models) {
return this->make_initialize(mdl, dyn_models.get(mdl.id), t);
});
}
......@@ -5229,12 +5220,12 @@ public:
time t,
flat_list<output_port_id>& o) noexcept
{
return dispatch(
mdl.type,
[ this, &mdl, t, &
o ]<typename DynamicsModels>(DynamicsModels & dyn_models) {
return this->make_transition(mdl, dyn_models.get(mdl.id), t, o);
});
return dispatch(mdl.type,
[this, &mdl, t, &o]<typename DynamicsModels>(
DynamicsModels& dyn_models) {
return this->make_transition(
mdl, dyn_models.get(mdl.id), t, o);
});
}
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment