Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Maintenance - Mise à jour mensuelle Lundi 6 Février entre 7h00 et 9h00
Open sidebar
Gauthier Quesnel
irritator
Commits
8653e4d8
Commit
8653e4d8
authored
Aug 25, 2020
by
Gauthier Quesnel
Browse files
gui: split node-editor in two files
parent
24457c11
Changes
4
Hide whitespace changes
Inline
Side-by-side
app/gui/CMakeLists.txt
View file @
8653e4d8
...
...
@@ -3,7 +3,7 @@ project(irritator-gui VERSION 0.1.0 LANGUAGES CXX)
set
(
gui_sources
dialog-file.cpp gui.hpp imnodes.cpp imnodes.hpp implot.h implot.cpp
window-logger.cpp node-editor.hpp node-editor.cpp
window-logger.cpp node-editor.hpp node-editor.cpp
simulation-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/node-editor.cpp
View file @
8653e4d8
...
...
@@ -167,125 +167,12 @@ static const char* dynamics_type_names[] = { "none",
"accumulator_2"
,
"flow"
};
static_assert
(
std
::
size
(
dynamics_type_names
)
==
static_cast
<
sz
>
(
dynamics_type_size
()));
static_assert
(
std
::
size
(
dynamics_type_names
)
==
static_cast
<
sz
>
(
dynamics_type_size
()));
static
window_logger
log_w
;
static
data_array
<
editor
,
editor_id
>
editors
;
static
void
observation_output_initialize
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
std
::
fill_n
(
output
->
xs
.
data
(),
output
->
xs
.
size
(),
0.
f
);
std
::
fill_n
(
output
->
ys
.
data
(),
output
->
ys
.
size
(),
0.
f
);
output
->
tl
=
t
;
output
->
min
=
-
1.
f
;
output
->
max
=
+
1.
f
;
output
->
id
=
0
;
}
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
if
(
!
output
->
ofs
.
is_open
())
{
if
(
output
->
observation_type
==
observation_output
::
type
::
both
)
output
->
observation_type
=
observation_output
::
type
::
multiplot
;
else
output
->
observation_type
=
observation_output
::
type
::
none
;
}
else
output
->
ofs
<<
"t,"
<<
output
->
name
<<
'\n'
;
}
}
static
void
observation_output_observe
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
,
const
irt
::
message
&
msg
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
const
auto
value
=
static_cast
<
float
>
(
msg
[
0
]);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
output
->
min
=
std
::
min
(
output
->
min
,
value
);
output
->
max
=
std
::
max
(
output
->
max
,
value
);
for
(
double
to_fill
=
output
->
tl
;
to_fill
<
t
;
to_fill
+=
obs
.
time_step
)
{
if
(
static_cast
<
size_t
>
(
output
->
id
)
<
output
->
xs
.
size
())
{
output
->
ys
[
output
->
id
]
=
value
;
output
->
xs
[
output
->
id
]
=
static_cast
<
float
>
(
t
);
++
output
->
id
;
}
}
}
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
output
->
ofs
<<
t
<<
','
<<
value
<<
'\n'
;
}
output
->
tl
=
t
;
}
static
void
observation_output_free
(
const
irt
::
observer
&
obs
,
const
irt
::
time
/*t*/
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
output
->
ofs
.
close
();
}
}
static
void
run_simulation
(
simulation
&
sim
,
double
begin
,
double
end
,
double
&
current
,
simulation_status
&
st
,
const
bool
&
stop
)
noexcept
{
current
=
begin
;
if
(
auto
ret
=
sim
.
initialize
(
current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation initialization failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
st
=
simulation_status
::
success
;
return
;
}
do
{
if
(
auto
ret
=
sim
.
run
(
current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
st
=
simulation_status
::
success
;
return
;
}
}
while
(
current
<
end
&&
!
stop
);
sim
.
clean
();
st
=
simulation_status
::
running_once_need_join
;
}
void
editor
::
clear
()
noexcept
{
...
...
@@ -2802,56 +2689,7 @@ editors_free(editor& ed)
editors
.
free
(
ed
);
}
static
void
initialize_observation
(
irt
::
editor
*
ed
)
noexcept
{
ed
->
observation_outputs
.
clear
();
observer
*
obs
=
nullptr
;
while
(
ed
->
sim
.
observers
.
next
(
obs
))
{
auto
*
output
=
ed
->
observation_outputs
.
emplace_back
(
obs
->
name
.
c_str
());
const
auto
type
=
ed
->
observation_types
[
get_index
(
ed
->
sim
.
observers
.
get_id
(
*
obs
))];
const
auto
diff
=
ed
->
simulation_end
-
ed
->
simulation_begin
;
const
auto
freq
=
diff
/
obs
->
time_step
;
const
auto
length
=
static_cast
<
size_t
>
(
freq
);
output
->
observation_type
=
type
;
if
(
match
(
type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
output
->
xs
.
init
(
length
);
output
->
ys
.
init
(
length
);
}
if
(
!
obs
->
name
.
empty
())
{
const
std
::
filesystem
::
path
obs_file_path
=
ed
->
observation_directory
/
obs
->
name
.
c_str
();
if
(
type
==
observation_output
::
type
::
file
||
type
==
observation_output
::
type
::
both
)
{
if
(
output
->
ofs
.
open
(
obs_file_path
);
!
output
->
ofs
.
is_open
())
log_w
.
log
(
4
,
"Fail to open "
"observation file: %s in "
"%s
\n
"
,
obs
->
name
.
c_str
(),
#if _WIN32
ed
->
observation_directory
.
u8string
().
c_str
());
#else
reinterpret_cast
<
const
char
*>
(
ed
->
observation_directory
.
u8string
().
c_str
()));
#endif
}
}
obs
->
initialize
=
&
observation_output_initialize
;
obs
->
observe
=
&
observation_output_observe
;
obs
->
free
=
&
observation_output_free
;
obs
->
user_data
=
static_cast
<
void
*>
(
output
);
}
}
static
editor
*
editor
*
make_combo_editor_name
(
editor_id
&
current
)
noexcept
{
editor
*
first
=
editors
.
try_to_get
(
current
);
...
...
@@ -2882,187 +2720,6 @@ make_combo_editor_name(editor_id& current) noexcept
return
editors
.
try_to_get
(
current
);
}
void
show_simulation_box
(
bool
*
show_simulation
)
{
ImGui
::
SetNextWindowPos
(
ImVec2
(
50
,
50
),
ImGuiCond_FirstUseEver
);
ImGui
::
SetNextWindowSize
(
ImVec2
(
250
,
350
),
ImGuiCond_Once
);
if
(
!
ImGui
::
Begin
(
"Simulation"
,
show_simulation
))
{
ImGui
::
End
();
return
;
}
static
editor_id
current
=
undefined
<
editor_id
>
();
if
(
auto
*
ed
=
make_combo_editor_name
(
current
);
ed
)
{
ImGui
::
InputDouble
(
"Begin"
,
&
ed
->
simulation_begin
);
ImGui
::
InputDouble
(
"End"
,
&
ed
->
simulation_end
);
ImGui
::
Checkbox
(
"Show values"
,
&
ed
->
simulation_show_value
);
if
(
ImGui
::
CollapsingHeader
(
"Simulation run one"
))
{
if
(
ed
->
st
==
simulation_status
::
running_once_need_join
)
{
if
(
ed
->
simulation_thread
.
joinable
())
{
ed
->
simulation_thread
.
join
();
ed
->
st
=
simulation_status
::
success
;
}
}
else
{
if
(
ImGui
::
Button
(
"run"
))
{
initialize_observation
(
ed
);
ed
->
st
=
simulation_status
::
running_once
;
ed
->
stop
=
false
;
ed
->
simulation_thread
=
std
::
thread
(
&
run_simulation
,
std
::
ref
(
ed
->
sim
),
ed
->
simulation_begin
,
ed
->
simulation_end
,
std
::
ref
(
ed
->
simulation_current
),
std
::
ref
(
ed
->
st
),
std
::
cref
(
ed
->
stop
));
}
}
if
(
ed
->
st
==
simulation_status
::
running_once
)
{
ImGui
::
SameLine
();
if
(
ImGui
::
Button
(
"Force stop"
))
ed
->
stop
=
true
;
}
}
if
(
match
(
ed
->
st
,
simulation_status
::
success
,
simulation_status
::
running_step
))
{
if
(
ImGui
::
CollapsingHeader
(
"Simulation step by step"
))
{
if
(
ImGui
::
Button
(
"init"
))
{
ed
->
sim
.
clean
();
initialize_observation
(
ed
);
ed
->
simulation_current
=
ed
->
simulation_begin
;
if
(
auto
ret
=
ed
->
sim
.
initialize
(
ed
->
simulation_current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation initialization failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
ed
->
st
=
simulation_status
::
success
;
}
else
{
ed
->
st
=
simulation_status
::
running_step
;
}
}
if
(
ed
->
st
==
simulation_status
::
running_step
)
{
ImGui
::
SameLine
();
if
(
ImGui
::
Button
(
"step"
))
{
if
(
ed
->
simulation_current
<
ed
->
simulation_end
)
{
if
(
auto
ret
=
ed
->
sim
.
run
(
ed
->
simulation_current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
ed
->
st
=
simulation_status
::
success
;
}
}
}
}
if
(
ed
->
st
==
simulation_status
::
running_step
)
{
ImGui
::
SameLine
();
if
(
ImGui
::
Button
(
"step x10"
))
{
for
(
int
i
=
0
;
i
<
10
;
++
i
)
{
if
(
ed
->
simulation_current
<
ed
->
simulation_end
)
{
if
(
auto
ret
=
ed
->
sim
.
run
(
ed
->
simulation_current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
ed
->
st
=
simulation_status
::
success
;
}
}
}
}
}
if
(
ed
->
st
==
simulation_status
::
running_step
)
{
ImGui
::
SameLine
();
if
(
ImGui
::
Button
(
"step x100"
))
{
for
(
int
i
=
0
;
i
<
100
;
++
i
)
{
if
(
ed
->
simulation_current
<
ed
->
simulation_end
)
{
if
(
auto
ret
=
ed
->
sim
.
run
(
ed
->
simulation_current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
ed
->
st
=
simulation_status
::
success
;
}
}
}
}
}
}
if
(
ImGui
::
CollapsingHeader
(
"Simulation until"
))
{
if
(
ImGui
::
Button
(
"init"
))
{
ed
->
sim
.
clean
();
initialize_observation
(
ed
);
ed
->
simulation_current
=
ed
->
simulation_begin
;
ed
->
simulation_until
=
static_cast
<
float
>
(
ed
->
simulation_begin
);
if
(
auto
ret
=
ed
->
sim
.
initialize
(
ed
->
simulation_current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation initialization failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
ed
->
st
=
simulation_status
::
success
;
}
else
{
ed
->
st
=
simulation_status
::
running_step
;
}
}
if
(
ed
->
st
==
simulation_status
::
running_step
)
{
ImGui
::
SliderFloat
(
"date"
,
&
ed
->
simulation_until
,
static_cast
<
float
>
(
ed
->
simulation_current
),
static_cast
<
float
>
(
ed
->
simulation_end
));
if
(
ImGui
::
Button
(
"run until"
))
{
while
(
ed
->
simulation_current
<
static_cast
<
double
>
(
ed
->
simulation_until
))
{
if
(
auto
ret
=
ed
->
sim
.
run
(
ed
->
simulation_current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
ed
->
st
=
simulation_status
::
success
;
}
}
}
}
}
}
if
(
match
(
ed
->
st
,
simulation_status
::
success
,
simulation_status
::
running_once
,
simulation_status
::
running_once_need_join
,
simulation_status
::
running_step
))
{
ImGui
::
Text
(
"Current: %g"
,
ed
->
simulation_current
);
const
double
duration
=
ed
->
simulation_end
-
ed
->
simulation_begin
;
const
double
elapsed
=
ed
->
simulation_current
-
ed
->
simulation_begin
;
const
double
fraction
=
elapsed
/
duration
;
ImGui
::
ProgressBar
(
static_cast
<
float
>
(
fraction
));
}
}
ImGui
::
End
();
}
static
void
show_settings_window
(
bool
*
is_open
)
{
...
...
@@ -3214,7 +2871,7 @@ node_editor_show()
log_w
.
show
(
&
show_log
);
if
(
show_simulation
)
show_simulation_box
(
&
show_simulation
);
show_simulation_box
(
log_w
,
&
show_simulation
);
if
(
show_plot
)
show_plot_box
(
&
show_plot
);
...
...
app/gui/node-editor.hpp
View file @
8653e4d8
...
...
@@ -354,6 +354,12 @@ struct editor
bool
show_editor
()
noexcept
;
};
editor
*
make_combo_editor_name
(
editor_id
&
current
)
noexcept
;
void
show_simulation_box
(
window_logger
&
log_w
,
bool
*
show_simulation
);
}
// namespace irt
#endif
...
...
app/gui/simulation-editor.cpp
0 → 100644
View file @
8653e4d8
// 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)
#ifdef _WIN32
#define NOMINMAX
#define WINDOWS_LEAN_AND_MEAN
#endif
#include
"gui.hpp"
#include
"imnodes.hpp"
#include
"implot.h"
#include
"node-editor.hpp"
#include
<fstream>
#include
<string>
#include
<fmt/format.h>
#include
<irritator/core.hpp>
#include
<irritator/io.hpp>
namespace
irt
{
static
void
observation_output_initialize
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
std
::
fill_n
(
output
->
xs
.
data
(),
output
->
xs
.
size
(),
0.
f
);
std
::
fill_n
(
output
->
ys
.
data
(),
output
->
ys
.
size
(),
0.
f
);
output
->
tl
=
t
;
output
->
min
=
-
1.
f
;
output
->
max
=
+
1.
f
;
output
->
id
=
0
;
}
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
if
(
!
output
->
ofs
.
is_open
())
{
if
(
output
->
observation_type
==
observation_output
::
type
::
both
)
output
->
observation_type
=
observation_output
::
type
::
multiplot
;
else
output
->
observation_type
=
observation_output
::
type
::
none
;
}
else
output
->
ofs
<<
"t,"
<<
output
->
name
<<
'\n'
;
}
}
static
void
observation_output_observe
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
,
const
irt
::
message
&
msg
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
const
auto
value
=
static_cast
<
float
>
(
msg
[
0
]);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
output
->
min
=
std
::
min
(
output
->
min
,
value
);
output
->
max
=
std
::
max
(
output
->
max
,
value
);
for
(
double
to_fill
=
output
->
tl
;
to_fill
<
t
;
to_fill
+=
obs
.
time_step
)
{
if
(
static_cast
<
size_t
>
(
output
->
id
)
<
output
->
xs
.
size
())
{
output
->
ys
[
output
->
id
]
=
value
;
output
->
xs
[
output
->
id
]
=
static_cast
<
float
>
(
t
);
++
output
->
id
;
}
}
}
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
output
->
ofs
<<
t
<<
','
<<
value
<<
'\n'
;
}
output
->
tl
=
t
;
}
static
void
observation_output_free
(
const
irt
::
observer
&
obs
,
const
irt
::
time
/*t*/
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
output
->
ofs
.
close
();
}
}
static
void
initialize_observation
(
window_logger
&
log_w
,
irt
::
editor
&
ed
)
noexcept
{
ed
.
observation_outputs
.
clear
();
observer
*
obs
=
nullptr
;
while
(
ed
.
sim
.
observers
.
next
(
obs
))
{
auto
*
output
=
ed
.
observation_outputs
.
emplace_back
(
obs
->
name
.
c_str
());
const
auto
type
=
ed
.
observation_types
[
get_index
(
ed
.
sim
.
observers
.
get_id
(
*
obs
))];
const
auto
diff
=
ed
.
simulation_end
-
ed
.
simulation_begin
;
const
auto
freq
=
diff
/
obs
->
time_step
;
const
auto
length
=
static_cast
<
size_t
>
(
freq
);
output
->
observation_type
=
type
;
if
(
match
(
type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
output
->
xs
.
init
(
length
);
output
->
ys
.
init
(
length
);
}
if
(
!
obs
->
name
.
empty
())
{
const
std
::
filesystem
::
path
obs_file_path
=
ed
.
observation_directory
/
obs
->
name
.
c_str
();
if
(
type
==
observation_output
::
type
::
file
||
type
==
observation_output
::
type
::
both
)
{
if
(
output
->
ofs
.
open
(
obs_file_path
);
!
output
->
ofs
.
is_open
())
log_w
.
log
(
4
,
"Fail to open "
"observation file: %s in "
"%s
\n
"
,
obs
->
name
.
c_str
(),
#if _WIN32
ed
.
observation_directory
.
u8string
().
c_str
());
#else
reinterpret_cast
<
const
char
*>
(
ed
.
observation_directory
.
u8string
().
c_str
()));
#endif
}
}
obs
->
initialize
=
&
observation_output_initialize
;
obs
->
observe
=
&
observation_output_observe
;
obs
->
free
=
&
observation_output_free
;
obs
->
user_data
=
static_cast
<
void
*>
(
output
);
}
}
static
void
run_simulation
(
window_logger
&
log_w
,
simulation
&
sim
,
double
begin
,
double
end
,
double
&
current
,
simulation_status
&
st
,
const
bool
&
stop
)
noexcept
{
current
=
begin
;
if
(
auto
ret
=
sim
.
initialize
(
current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation initialization failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
st
=
simulation_status
::
success
;
return
;
}
do
{
if
(
auto
ret
=
sim
.
run
(
current
);
irt
::
is_bad
(
ret
))
{
log_w
.
log
(
3
,
"Simulation failure (%s)
\n
"
,
irt
::
status_string
(
ret
));
st
=
simulation_status
::
success
;
return
;
}
}
while
(
current
<
end
&&
!
stop
);
sim
.
clean
();
st
=
simulation_status
::
running_once_need_join
;
}
static
void
show_simulation_run_once
(
window_logger
&
log_w
,
editor
&
ed
)
{
if
(
ed
.
st
==
simulation_status
::
running_once_need_join
)
{
if
(
ed
.
simulation_thread
.
joinable
())
{
ed
.
simulation_thread
.
join
();
ed
.
st
=
simulation_status
::
success
;
}
}
else
{