Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Gauthier Quesnel
irritator
Commits
c45b6837
Commit
c45b6837
authored
Jun 07, 2020
by
Gauthier Quesnel
Browse files
gui: add a group/ungroup mode
parent
f9d78d8d
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
app/gui/CMakeLists.txt
View file @
c45b6837
...
...
@@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project
(
irritator-gui VERSION 0.1.0 LANGUAGES CXX
)
set
(
gui_sources
dialog-file.cpp imnodes.cpp imnodes.hpp window-logger.cpp node-editor.cpp
dialog-file.cpp gui.hpp imnodes.cpp imnodes.hpp window-logger.cpp
node-editor.hpp node-editor.cpp
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui.cpp
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui.h
${
PROJECT_SOURCE_DIR
}
/../../external/imgui/imgui_demo.cpp
...
...
app/gui/dialog-file.cpp
View file @
c45b6837
...
...
@@ -3,6 +3,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include
"gui.hpp"
#include
"node-editor.hpp"
#include
<fmt/format.h>
...
...
app/gui/gui.hpp
View file @
c45b6837
...
...
@@ -5,21 +5,10 @@
#ifndef ORG_VLEPROJECT_IRRITATOR_APP_GUI_2020
#define ORG_VLEPROJECT_IRRITATOR_APP_GUI_2020
#include
<imgui.h>
#include
<filesystem>
#include
<string>
namespace
irt
{
enum
class
simulation_status
{
success
,
running
,
uninitialized
,
internal_error
,
};
void
node_editor_initialize
();
...
...
@@ -29,22 +18,6 @@ node_editor_show();
void
node_editor_shutdown
();
struct
window_logger
{
ImGuiTextBuffer
buffer
;
ImGuiTextFilter
filter
;
ImVector
<
int
>
line_offsets
;
bool
auto_scroll
=
true
;
bool
scroll_to_bottom
=
false
;
window_logger
()
=
default
;
void
clear
()
noexcept
;
void
log
(
const
int
level
,
const
char
*
fmt
,
...)
IM_FMTARGS
(
3
);
void
log
(
const
int
level
,
const
char
*
fmt
,
va_list
args
)
IM_FMTLIST
(
3
);
void
show
(
bool
*
is_show
);
};
/* Filesytem dialog box */
bool
...
...
app/gui/imnodes.cpp
View file @
c45b6837
...
...
@@ -1942,6 +1942,35 @@ SetNodeGridSpacePos(int node_id, const ImVec2& grid_pos)
node
.
origin
=
grid_pos
;
}
ImVec2
GetNodeScreenSpacePos
(
int
node_id
)
{
// Remember to call Initialize() before using any other functions!
assert
(
initialized
);
EditorContext
&
editor
=
editor_context_get
();
NodeData
&
node
=
editor
.
nodes
.
find_or_create_new
(
node_id
);
return
grid_space_to_editor_space
(
node
.
origin
);
}
ImVec2
GetNodeGridSpacePos
(
int
node_id
)
{
// Remember to call Initialize() before using any other functions!
assert
(
initialized
);
EditorContext
&
editor
=
editor_context_get
();
NodeData
&
node
=
editor
.
nodes
.
find_or_create_new
(
node_id
);
return
node
.
origin
;
}
void
ClearSelectedNodesAndLinks
()
{
assert
(
initialized
);
EditorContext
&
editor
=
editor_context_get
();
editor
.
selected_link_indices
.
clear
();
editor
.
selected_node_indices
.
clear
();
}
void
SetNodeDraggable
(
int
node_id
,
const
bool
draggable
)
{
...
...
app/gui/imnodes.hpp
View file @
c45b6837
...
...
@@ -272,6 +272,12 @@ void
SetNodeScreenSpacePos
(
int
node_id
,
const
ImVec2
&
screen_space_pos
);
void
SetNodeGridSpacePos
(
int
node_id
,
const
ImVec2
&
grid_pos
);
ImVec2
GetNodeScreenSpacePos
(
int
node_id
);
ImVec2
GetNodeGridSpacePos
(
int
node_id
);
// Enable or disable the ability to click and drag a specific node.
void
SetNodeDraggable
(
int
node_id
,
const
bool
draggable
);
...
...
@@ -304,6 +310,9 @@ GetSelectedNodes(int* node_ids);
void
GetSelectedLinks
(
int
*
link_ids
);
void
ClearSelectedNodesAndLinks
();
// Was the previous attribute active? This will continuously return true while
// the left mouse button is being pressed over the UI content of the attribute.
bool
...
...
app/gui/node-editor.cpp
View file @
c45b6837
This diff is collapsed.
Click to expand it.
app/gui/node-editor.hpp
0 → 100644
View file @
c45b6837
// Copyright (c) 2020 INRA Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef ORG_VLEPROJECT_IRRITATOR_APP_NODE_EDITOR_2020
#define ORG_VLEPROJECT_IRRITATOR_APP_NODE_EDITOR_2020
#include
<irritator/core.hpp>
#include
<filesystem>
#include
<fstream>
#include
<thread>
#include
<unordered_map>
#include
<variant>
#include
<vector>
#include
"imnodes.hpp"
#include
<imgui.h>
namespace
irt
{
template
<
typename
Identifier
>
constexpr
Identifier
undefined
()
noexcept
{
static_assert
(
std
::
is_enum
<
Identifier
>::
value
,
"Identifier must be a enumeration: enum class id : unsigned {};"
);
return
static_cast
<
Identifier
>
(
0
);
}
enum
class
editor_id
:
u64
;
enum
class
cluster_id
:
u64
;
using
child_id
=
std
::
variant
<
model_id
,
cluster_id
>
;
enum
class
simulation_status
{
success
,
running
,
uninitialized
,
internal_error
,
};
static
inline
constexpr
int
not_found
=
-
1
;
struct
top_cluster
{
std
::
vector
<
child_id
>
children
;
std
::
vector
<
int
>
nodes
;
int
next_node_id
=
0
;
static
inline
constexpr
int
not_found
=
-
1
;
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
;
return
static_cast
<
int
>
(
std
::
distance
(
std
::
begin
(
children
),
it
));
}
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
;
return
static_cast
<
int
>
(
std
::
distance
(
std
::
begin
(
nodes
),
it
));
}
//const child_id get_child(const int node) const noexcept
//{
// if (auto found = get_index(node); found != not_found)
// return children[found];
// return undefined<child_id>();
//}
//const int get_node(const child_id id) const noexcept
//{
// if (auto found = get_index(id); found != not_found)
// return nodes[found];
// 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
)
{
children
.
emplace_back
(
id
);
nodes
.
emplace_back
(
next_node_id
);
++
next_node_id
;
}
};
struct
cluster
{
cluster
()
=
default
;
small_string
<
16
>
name
;
std
::
vector
<
child_id
>
children
;
std
::
vector
<
input_port_id
>
input_ports
;
std
::
vector
<
output_port_id
>
output_ports
;
int
get
(
const
child_id
id
)
const
noexcept
{
for
(
size_t
i
=
0
,
e
=
children
.
size
();
i
!=
e
;
++
i
)
if
(
id
==
children
[
i
])
return
static_cast
<
int
>
(
i
);
return
not_found
;
}
};
struct
window_logger
{
ImGuiTextBuffer
buffer
;
ImGuiTextFilter
filter
;
ImVector
<
int
>
line_offsets
;
bool
auto_scroll
=
true
;
bool
scroll_to_bottom
=
false
;
window_logger
()
=
default
;
void
clear
()
noexcept
;
void
log
(
const
int
level
,
const
char
*
fmt
,
...)
IM_FMTARGS
(
3
);
void
log
(
const
int
level
,
const
char
*
fmt
,
va_list
args
)
IM_FMTLIST
(
3
);
void
show
(
bool
*
is_show
);
};
struct
observation_output
{
enum
class
type
{
none
,
plot
,
file
,
both
};
observation_output
()
=
default
;
observation_output
(
const
char
*
name_
)
:
name
(
name_
)
{}
std
::
ofstream
ofs
;
const
char
*
name
=
nullptr
;
array
<
float
>
data
;
double
tl
=
0.0
;
float
min
=
-
1.
f
;
float
max
=
+
1.
f
;
int
id
=
0
;
type
observation_type
=
type
::
none
;
};
struct
editor
{
small_string
<
16
>
name
;
std
::
filesystem
::
path
path
;
imnodes
::
EditorContext
*
context
=
nullptr
;
bool
initialized
=
false
;
bool
show
=
true
;
simulation
sim
;
double
simulation_begin
=
0.0
;
double
simulation_end
=
10.0
;
double
simulation_current
=
10.0
;
std
::
thread
simulation_thread
;
simulation_status
st
=
simulation_status
::
uninitialized
;
bool
simulation_show_value
=
false
;
bool
stop
=
false
;
vector
<
observation_output
>
observation_outputs
;
array
<
observation_output
::
type
>
observation_types
;
std
::
filesystem
::
path
observation_directory
;
data_array
<
cluster
,
cluster_id
>
clusters
;
array
<
cluster_id
>
clusters_mapper
;
/* group per cluster_id */
array
<
cluster_id
>
models_mapper
;
/* group per model_id */
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
;
void
free_group
(
cluster
&
group
)
noexcept
;
void
free_children
(
const
ImVector
<
int
>&
nodes
)
noexcept
;
void
copy_group
(
const
child_id
*
sources
,
const
size_t
size
,
child_id
*
destination
)
noexcept
;
void
reorder_subgroup
(
const
size_t
from
,
const
size_t
length
,
ImVec2
click_pos
)
noexcept
;
cluster_id
parent
(
cluster_id
child
)
const
noexcept
{
return
clusters_mapper
[
get_index
(
child
)];
}
cluster_id
parent
(
model_id
child
)
const
noexcept
{
return
models_mapper
[
get_index
(
child
)];
}
void
parent
(
const
cluster_id
child
,
const
cluster_id
parent
)
noexcept
{
clusters_mapper
[
get_index
(
child
)]
=
parent
;
}
void
parent
(
const
model_id
child
,
const
cluster_id
parent
)
noexcept
{
models_mapper
[
get_index
(
child
)]
=
parent
;
}
int
get_in
(
input_port_id
id
)
const
noexcept
{
return
static_cast
<
int
>
(
get_index
(
id
));
}
input_port_id
get_in
(
int
index
)
const
noexcept
{
auto
*
port
=
sim
.
input_ports
.
try_to_get
(
static_cast
<
u32
>
(
index
));
return
port
?
sim
.
input_ports
.
get_id
(
port
)
:
undefined
<
input_port_id
>
();
}
int
get_out
(
output_port_id
id
)
const
noexcept
{
constexpr
u32
is_output
=
1
<<
31
;
u32
index
=
get_index
(
id
);
index
|=
is_output
;
return
static_cast
<
int
>
(
index
);
}
output_port_id
get_out
(
int
index
)
const
noexcept
{
constexpr
u32
mask
=
~
(
1
<<
31
);
/* remove the first bit */
index
&=
mask
;
auto
*
port
=
sim
.
output_ports
.
try_to_get
(
static_cast
<
u32
>
(
index
));
return
port
?
sim
.
output_ports
.
get_id
(
port
)
:
undefined
<
output_port_id
>
();
}
status
add_lotka_volterra
()
noexcept
;
status
add_izhikevitch
()
noexcept
;
void
show_connections
()
noexcept
;
void
show_model_dynamics
(
model
&
mdl
)
noexcept
;
void
show_model_cluster
(
cluster
&
mdl
)
noexcept
;
void
show_top
()
noexcept
;
bool
show_editor
()
noexcept
;
};
}
// namespace irt
#endif
\ No newline at end of file
app/gui/window-logger.cpp
View file @
c45b6837
...
...
@@ -2,7 +2,7 @@
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include
"
gui
.hpp"
#include
"
node-editor
.hpp"
namespace
irt
{
...
...
lib/include/irritator/core.hpp
View file @
c45b6837
...
...
@@ -4411,6 +4411,48 @@ struct simulation
});
}
template
<
typename
Function
>
void
for_all_input_port
(
const
model
&
mdl
,
Function
f
)
{
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
;
});
}
template
<
typename
Function
>
void
for_all_output_port
(
const
model
&
mdl
,
Function
f
)
{
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
;
});
}
status
get_input_port_index
(
const
model
&
mdl
,
const
input_port_id
port
,
int
*
index
)
const
noexcept
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment