Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Gauthier Quesnel
irritator
Commits
0948a248
Commit
0948a248
authored
Jun 06, 2021
by
Gauthier Quesnel
Browse files
core: refactor external-source from app to editor
parent
fe9c0ab7
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
app/gui/application.cpp
View file @
0948a248
...
...
@@ -4,23 +4,21 @@
#include "application.hpp"
#include "dialog.hpp"
#include "node-editor.hpp"
#include <irritator/core.hpp>
#include <chrono>
#include "internal.hpp"
namespace
irt
{
bool
application
::
init
()
bool
application
::
init
()
{
if
(
auto
ret
=
editors
.
init
(
50u
);
is_bad
(
ret
))
{
log_w
.
log
(
2
,
"Fail to initialize irritator: %s
\n
"
,
status_string
(
ret
));
std
::
fprintf
(
stderr
,
"Fail to initialize irritator: %s
\n
"
,
status_string
(
ret
));
std
::
fprintf
(
stderr
,
"Fail to initialize irritator: %s
\n
"
,
status_string
(
ret
));
return
false
;
}
if
(
auto
*
ed
=
app
.
alloc_editor
();
ed
)
{
if
(
auto
*
ed
=
alloc_editor
();
ed
)
{
ed
->
context
=
imnodes
::
EditorContextCreate
();
ed
->
settings
.
compute_colors
();
}
...
...
@@ -58,7 +56,7 @@ bool application::init()
}
bool
void
application
::
show
()
application
::
show
()
{
bool
ret
=
true
;
...
...
@@ -83,7 +81,6 @@ void application::show()
ImGui
::
MenuItem
(
"Simulation"
,
nullptr
,
&
show_simulation
);
ImGui
::
MenuItem
(
"Plot"
,
nullptr
,
&
show_plot
);
ImGui
::
MenuItem
(
"Sources"
,
nullptr
,
&
show_sources_window
);
ImGui
::
MenuItem
(
"Settings"
,
nullptr
,
&
show_settings
);
ImGui
::
MenuItem
(
"Log"
,
nullptr
,
&
show_log
);
...
...
@@ -123,25 +120,17 @@ void application::show()
log_w
.
show
(
&
show_log
);
if
(
show_settings
)
settings
.
show
(
&
show_settings
);
show_settings
_window
(
);
if
(
show_demo
)
ImGui
::
ShowDemoWindow
();
if
(
show_sources_window
)
show_sources
(
&
show_sources_window
);
return
ret
;
}
editor
*
application
::
alloc_editor
()
{
if
(
srcs
.
binary_file_sources
.
capacity
()
==
0
)
{
srcs
.
init
(
50
);
}
if
(
!
editors
.
can_alloc
(
1u
))
{
log_w
.
log
(
2
,
"Too many open editor
\n
"
);
return
nullptr
;
...
...
@@ -176,7 +165,7 @@ application::show_plot_window()
}
static
editor_id
current
=
undefined
<
editor_id
>
();
if
(
auto
*
ed
=
make_combo_editor_name
(
*
this
,
current
);
ed
)
{
if
(
auto
*
ed
=
make_combo_editor_name
(
current
);
ed
)
{
if
(
ImPlot
::
BeginPlot
(
"simulation"
,
"t"
,
"s"
))
{
ImPlot
::
PushStyleVar
(
ImPlotStyleVar_LineWeight
,
1.
f
);
...
...
@@ -197,8 +186,8 @@ application::show_plot_window()
ImGui
::
End
();
}
void
application
::
show_settings_window
()
void
application
::
show_settings_window
()
{
ImGui
::
SetNextWindowPos
(
ImVec2
(
300
,
300
),
ImGuiCond_FirstUseEver
);
ImGui
::
SetNextWindowSize
(
ImVec2
(
350
,
400
),
ImGuiCond_Once
);
...
...
@@ -210,7 +199,7 @@ void application::show_settings_window()
ImGui
::
Text
(
"Home.......: %s"
,
home_dir
.
u8string
().
c_str
());
ImGui
::
Text
(
"Executable.: %s"
,
executable_dir
.
u8string
().
c_str
());
ImGui
::
End
();
ImGui
::
End
();
}
void
...
...
@@ -222,10 +211,10 @@ application::shutdown()
}
static
status
simulation_run_for
(
simulation
&
sim
,
long
long
int
duration_in_microseconds
,
const
double
end
,
double
&
current
)
noexcept
run_for
(
editor
&
ed
,
long
long
int
duration_in_microseconds
,
const
double
end
,
double
&
current
)
noexcept
{
namespace
stdc
=
std
::
chrono
;
...
...
@@ -233,8 +222,8 @@ simulation_run_for(simulation& sim,
long
long
int
duration_since_start
;
do
{
if
(
sim
.
current_status
=
sim
.
run
(
current
);
is_bad
(
sim
.
current_status
))
return
ret
;
if
(
auto
ret
=
ed
.
sim
.
run
(
current
);
is_bad
(
ret
))
return
ret
;
auto
end_at
=
stdc
::
high_resolution_clock
::
now
();
auto
duration
=
end_at
-
start_at
;
...
...
@@ -245,24 +234,63 @@ simulation_run_for(simulation& sim,
return
status
::
success
;
}
void
application
::
run_simulations
()
void
application
::
run_simulations
()
{
int
running_simulation
=
0
;
editor
*
ed
=
nullptr
;
while
(
editors
.
next
(
ed
))
if
(
ed
->
st
=
editor_status
::
running
)
if
(
match
(
ed
->
st
,
editor_status
::
running_debug
,
editor_status
::
running_thread
,
editor_status
::
running_thread_need_join
))
++
running_simulation
;
if
(
!
running_simulation
)
return
;
auto
duration
=
10000
/
running_simulation
;
ed
=
nullptr
;
while
(
editors
.
next
(
ed
))
if
(
ed
->
st
=
editor_status
::
running
)
ed
->
sim_st
=
run_for
(
ed
->
sim
,
duration
,
ed
->
simulation_end
,
ed
->
simulation_current
);
if
(
match
(
ed
->
st
,
editor_status
::
running_debug
,
editor_status
::
running_thread
,
editor_status
::
running_thread_need_join
))
ed
->
sim_st
=
run_for
(
*
ed
,
duration
,
ed
->
simulation_end
,
ed
->
simulation_current
);
}
editor
*
application
::
make_combo_editor_name
(
editor_id
&
current
)
noexcept
{
editor
*
first
=
editors
.
try_to_get
(
current
);
if
(
first
==
nullptr
)
{
if
(
!
editors
.
next
(
first
))
{
current
=
undefined
<
editor_id
>
();
return
nullptr
;
}
}
current
=
editors
.
get_id
(
first
);
if
(
ImGui
::
BeginCombo
(
"Name"
,
first
->
name
.
c_str
()))
{
editor
*
ed
=
nullptr
;
while
(
editors
.
next
(
ed
))
{
const
bool
is_selected
=
current
==
editors
.
get_id
(
ed
);
if
(
ImGui
::
Selectable
(
ed
->
name
.
c_str
(),
is_selected
))
current
=
editors
.
get_id
(
ed
);
if
(
is_selected
)
ImGui
::
SetItemDefaultFocus
();
}
ImGui
::
EndCombo
();
}
return
editors
.
try_to_get
(
current
);
}
}
// namespace irt
app/gui/application.hpp
View file @
0948a248
...
...
@@ -9,26 +9,434 @@
#include <irritator/external_source.hpp>
#include <filesystem>
#include <optional>
#include <fstream>
#include <map>
#include <thread>
#include <variant>
#include <vector>
#include "imnodes.hpp"
#include "implot.h"
#include <imgui.h>
namespace
irt
{
struct
application
;
struct
cluster
;
struct
editor
;
struct
top_cluster
;
struct
window_logger
;
struct
plot_output
;
struct
file_output
;
struct
file_discrete_output
;
static
inline
constexpr
int
not_found
=
-
1
;
enum
class
editor_id
:
u64
;
enum
class
cluster_id
:
u64
;
enum
class
plot_output_id
:
u64
;
enum
class
file_output_id
:
u64
;
enum
class
file_discrete_output_id
:
u64
;
using
child_id
=
std
::
variant
<
model_id
,
cluster_id
>
;
using
observation_output
=
std
::
variant
<
std
::
monostate
,
plot_output_id
,
file_output_id
,
file_discrete_output_id
>
;
enum
class
editor_status
{
editing
,
initializing
,
running_debug
,
running_thread
,
running_thread_need_join
};
struct
plot_output
{
plot_output
()
=
default
;
plot_output
(
std
::
string_view
name_
)
:
name
(
name_
)
{}
void
operator
()(
const
irt
::
observer
&
obs
,
const
irt
::
dynamics_type
/*type*/
,
const
irt
::
time
tl
,
const
irt
::
time
t
,
const
irt
::
observer
::
status
s
);
editor
*
ed
=
nullptr
;
std
::
vector
<
float
>
xs
;
std
::
vector
<
float
>
ys
;
small_string
<
24u
>
name
;
double
tl
=
0.0
;
double
time_step
=
0.01
;
};
struct
file_output
{
file_output
()
=
default
;
file_output
(
std
::
string_view
name_
)
:
name
(
name_
)
{}
void
operator
()(
const
irt
::
observer
&
obs
,
const
irt
::
dynamics_type
type
,
const
irt
::
time
tl
,
const
irt
::
time
t
,
const
irt
::
observer
::
status
s
);
editor
*
ed
=
nullptr
;
std
::
ofstream
ofs
;
small_string
<
24u
>
name
;
};
struct
file_discrete_output
{
file_discrete_output
()
=
default
;
file_discrete_output
(
std
::
string_view
name_
)
:
name
(
name_
)
{}
void
operator
()(
const
irt
::
observer
&
obs
,
const
irt
::
dynamics_type
type
,
const
irt
::
time
tl
,
const
irt
::
time
t
,
const
irt
::
observer
::
status
s
);
editor
*
ed
=
nullptr
;
std
::
ofstream
ofs
;
small_string
<
24u
>
name
;
double
tl
=
0.0
;
double
time_step
=
0.01
;
};
struct
cluster
{
cluster
()
=
default
;
small_string
<
16
>
name
;
std
::
vector
<
child_id
>
children
;
std
::
vector
<
int
>
input_ports
;
std
::
vector
<
int
>
output_ports
;
int
get
(
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
));
}
};
struct
top_cluster
{
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
{
for
(
int
i
=
0
,
e
=
length
(
children
);
i
!=
e
;
++
i
)
if
(
children
[
i
].
first
==
id
)
return
i
;
return
not_found
;
}
int
get_index
(
const
int
node
)
const
noexcept
{
for
(
int
i
=
0
,
e
=
length
(
children
);
i
!=
e
;
++
i
)
if
(
children
[
i
].
second
==
node
)
return
i
;
return
not_found
;
}
void
clear
()
noexcept
{
children
.
clear
();
}
void
pop
(
const
int
index
)
noexcept
{
std
::
swap
(
children
[
index
],
children
.
back
());
children
.
pop_back
();
}
int
emplace_back
(
const
child_id
id
)
{
int
ret
=
next_node_id
++
;
children
.
emplace_back
(
id
,
ret
);
return
ret
;
}
};
inline
int
make_input_node_id
(
const
irt
::
model_id
mdl
,
const
int
port
)
noexcept
;
inline
int
make_output_node_id
(
const
irt
::
model_id
mdl
,
const
int
port
)
noexcept
;
inline
std
::
pair
<
irt
::
u32
,
irt
::
u32
>
get_model_input_port
(
const
int
node_id
)
noexcept
;
inline
std
::
pair
<
irt
::
u32
,
irt
::
u32
>
get_model_output_port
(
const
int
node_id
)
noexcept
;
struct
editor
{
small_string
<
16
>
name
;
std
::
filesystem
::
path
path
;
imnodes
::
EditorContext
*
context
=
nullptr
;
bool
initialized
=
false
;
bool
show
=
true
;
simulation
sim
;
external_source
srcs
;
double
simulation_begin
=
0.0
;
double
simulation_end
=
10.0
;
double
simulation_current
=
10.0
;
double
simulation_next_time
=
0.0
;
long
simulation_bag_id
=
0
;
double
simulation_during_date
;
int
simulation_during_bag
;
std
::
thread
simulation_thread
;
editor_status
st
=
editor_status
::
editing
;
status
sim_st
=
status
::
success
;
bool
simulation_show_value
=
false
;
bool
stop
=
false
;
data_array
<
plot_output
,
plot_output_id
>
plot_outs
;
data_array
<
file_output
,
file_output_id
>
file_outs
;
data_array
<
file_discrete_output
,
file_discrete_output_id
>
file_discrete_outs
;
std
::
vector
<
observation_output
>
observation_outputs
;
void
show_sources_window
(
bool
*
is_show
);
void
show_menu_sources
(
const
char
*
title
,
source
&
src
);
template
<
typename
Function
,
typename
...
Args
>
constexpr
void
observation_dispatch
(
const
u32
index
,
Function
&&
f
,
Args
...
args
)
noexcept
{
switch
(
observation_outputs
[
index
].
index
())
{
case
1
:
f
(
plot_outs
,
std
::
get
<
plot_output_id
>
(
observation_outputs
[
index
]),
args
...);
break
;
case
2
:
f
(
file_outs
,
std
::
get
<
file_output_id
>
(
observation_outputs
[
index
]),
args
...);
break
;
case
3
:
f
(
file_discrete_outs
,
std
::
get
<
file_discrete_output_id
>
(
observation_outputs
[
index
]),
args
...);
break
;
default:
break
;
}
}
void
observation_outputs_free
(
const
u32
index
)
noexcept
{
observation_dispatch
(
index
,
[](
auto
&
outs
,
auto
out_id
)
{
outs
.
free
(
out_id
);
});
observation_outputs
[
index
]
=
std
::
monostate
{};
}
std
::
filesystem
::
path
observation_directory
;
data_array
<
cluster
,
cluster_id
>
clusters
;
std
::
vector
<
cluster_id
>
clusters_mapper
;
/* group per cluster_id */
std
::
vector
<
cluster_id
>
models_mapper
;
/* group per model_id */
std
::
vector
<
bool
>
models_make_transition
;
ImVector
<
ImVec2
>
positions
;
ImVector
<
ImVec2
>
displacements
;
bool
use_real_time
;
bool
starting
=
true
;
double
synchronize_timestep
;
top_cluster
top
;
std
::
string
tooltip
;
bool
show_load_file_dialog
=
false
;
bool
show_save_file_dialog
=
false
;
bool
show_select_directory_dialog
=
false
;
bool
show_settings
=
false
;
bool
show_sources
=
false
;
struct
settings_manager
{
int
kernel_model_cache
=
1024
;
int
kernel_message_cache
=
32768
;
int
gui_node_cache
=
1024
;
ImVec4
gui_model_color
{
.27
f
,
.27
f
,
.54
f
,
1.
f
};
ImVec4
gui_model_transition_color
{
.27
f
,
.54
f
,
.54
f
,
1.
f
};
ImVec4
gui_cluster_color
{
.27
f
,
.54
f
,
.27
f
,
1.
f
};
ImU32
gui_hovered_model_color
;
ImU32
gui_selected_model_color
;
ImU32
gui_hovered_model_transition_color
;
ImU32
gui_selected_model_transition_color
;
ImU32
gui_hovered_cluster_color
;
ImU32
gui_selected_cluster_color
;
int
automatic_layout_iteration_limit
=
200
;
float
automatic_layout_x_distance
=
350.
f
;
float
automatic_layout_y_distance
=
350.
f
;
float
grid_layout_x_distance
=
250.
f
;
float
grid_layout_y_distance
=
250.
f
;
bool
show_dynamics_inputs_in_editor
=
false
;
void
compute_colors
()
noexcept
;
void
show
(
bool
*
is_open
);
}
settings
;
status
initialize
(
u32
id
)
noexcept
;
void
clear
()
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
;
status
copy
(
const
ImVector
<
int
>&
nodes
)
noexcept
;
void
compute_grid_layout
()
noexcept
;
void
compute_automatic_layout
()
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
{
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
;
}
struct
gport
{
gport
()
noexcept
=
default
;
gport
(
irt
::
model
*
model_
,
const
int
port_index_
)
noexcept
:
model
(
model_
)
,
port_index
(
port_index_
)
{}
irt
::
model
*
model
=
nullptr
;
int
port_index
=
0
;
};
gport
get_in
(
const
int
index
)
noexcept
{
const
auto
model_index_port
=
get_model_input_port
(
index
);
auto
*
mdl
=
sim
.
models
.
try_to_get
(
model_index_port
.
first
);
return
{
mdl
,
static_cast
<
int
>
(
model_index_port
.
second
)
};
}
gport
get_out
(
const
int
index
)
noexcept
{
const
auto
model_index_port
=
get_model_output_port
(
index
);
auto
*
mdl
=
sim
.
models
.
try_to_get
(
model_index_port
.
first
);
return
{
mdl
,
static_cast
<
int
>
(
model_index_port
.
second
)
};
}
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
;
};
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
application
{
data_array
<
editor
,
editor_id
>
editors
;