1
+ #include < cstdint>
1
2
#include < fstream>
2
3
#include < iostream>
4
+ #include < iterator>
3
5
#include < sstream>
4
6
#include < string>
5
7
6
8
#include < rerun.hpp>
9
+ #include < rerun/third_party/cxxopts.hpp>
10
+ #include < string_view>
11
+
12
+ void set_time_from_args (const rerun::RecordingStream& rec, cxxopts::ParseResult& args) {
13
+ if (args.count (" time" )) {
14
+ const auto times = args[" time" ].as <std::vector<std::string>>();
15
+ for (const auto & time_str : times) {
16
+ auto pos = time_str.find (' =' );
17
+ if (pos != std::string::npos) {
18
+ auto timeline_name = time_str.substr (0 , pos);
19
+ int64_t time = std::stol (time_str.substr (pos + 1 ));
20
+ rec.set_time_seconds (timeline_name, static_cast <double >(time ));
21
+ }
22
+ }
23
+ }
24
+
25
+ if (args.count (" sequence" )) {
26
+ const auto sequences = args[" sequence" ].as <std::vector<std::string>>();
27
+ for (const auto & sequence_str : sequences) {
28
+ auto pos = sequence_str.find (' =' );
29
+ if (pos != std::string::npos) {
30
+ auto timeline_name = sequence_str.substr (0 , pos);
31
+ int64_t sequence = std::stol (sequence_str.substr (pos + 1 ));
32
+ rec.set_time_sequence (timeline_name, sequence);
33
+ }
34
+ }
35
+ }
36
+ }
7
37
8
- static const char * USAGE = R"(
38
+ int main (int argc, char * argv[]) {
39
+ // The Rerun Viewer will always pass these two pieces of information:
40
+ // 1. The path to be loaded, as a positional arg.
41
+ // 2. A shared recording ID, via the `--recording-id` flag.
42
+ //
43
+ // It is up to you whether you make use of that shared recording ID or not.
44
+ // If you use it, the data will end up in the same recording as all other plugins interested in
45
+ // that file, otherwise you can just create a dedicated recording for it. Or both.
46
+ //
47
+ // Check out `re_data_source::DataLoaderSettings` documentation for an exhaustive listing of
48
+ // the available CLI parameters.
49
+
50
+ cxxopts::Options options (
51
+ " rerun-loader-cpp-file" ,
52
+ R"(
9
53
This is an example executable data-loader plugin for the Rerun Viewer.
10
54
Any executable on your `$PATH` with a name that starts with `rerun-loader-` will be treated as an
11
55
external data-loader.
@@ -15,57 +59,38 @@ special exit code to indicate that it doesn't support anything else.
15
59
16
60
To try it out, compile it and place it in your $PATH as `rerun-loader-cpp-file`, then open a C++ source
17
61
file with Rerun (`rerun file.cpp`).
62
+ )"
63
+ );
18
64
19
- USAGE:
20
- rerun-loader-cpp-file [OPTIONS] FILEPATH
21
-
22
- FLAGS:
23
- -h, --help Prints help information
24
-
25
- OPTIONS:
26
- --recording-id RECORDING_ID ID of the shared recording
27
-
28
- ARGS:
29
- <FILEPATH>
30
- )" ;
31
-
32
- int main (int argc, char * argv[]) {
33
- // The Rerun Viewer will always pass these two pieces of information:
34
- // 1. The path to be loaded, as a positional arg.
35
- // 2. A shared recording ID, via the `--recording-id` flag.
36
- //
37
- // It is up to you whether you make use of that shared recording ID or not.
38
- // If you use it, the data will end up in the same recording as all other plugins interested in
39
- // that file, otherwise you can just create a dedicated recording for it. Or both.
40
- std::string filepath;
41
- std::string recording_id;
42
-
43
- for (int i = 1 ; i < argc; ++i) {
44
- std::string arg (argv[i]);
45
-
46
- if (arg == " --recording-id" ) {
47
- if (i + 1 < argc) {
48
- recording_id = argv[i + 1 ];
49
- ++i;
50
- } else {
51
- std::cerr << USAGE << std::endl;
52
- return 1 ;
53
- }
54
- } else {
55
- filepath = arg;
56
- }
65
+ // clang-format off
66
+ options.add_options ()
67
+ (" h,help" , " Print usage" )
68
+ (" filepath" , " The filepath to be loaded and logged" , cxxopts::value<std::string>())
69
+ (" application-id" , " Optional recommended ID for the application" , cxxopts::value<std::string>())
70
+ (" recording-id" , " Optional recommended ID for the recording" , cxxopts::value<std::string>())
71
+ (" entity-path-prefix" , " Optional prefix for all entity paths" , cxxopts::value<std::string>())
72
+ (" timeless" , " Optionally mark data to be logged as timeless" , cxxopts::value<bool >()->default_value (" false" ))
73
+ (" time" , " Optional timestamps to log at (e.g. `--time sim_time=1709203426`) (repeatable)" , cxxopts::value<std::vector<std::string>>())
74
+ (" sequence" , " Optional sequences to log at (e.g. `--sequence sim_frame=42`) (repeatable)" , cxxopts::value<std::vector<std::string>>())
75
+ ;
76
+ // clang-format on
77
+
78
+ options.parse_positional ({" filepath" });
79
+
80
+ auto args = options.parse (argc, argv);
81
+
82
+ if (args.count (" help" )) {
83
+ std::cout << options.help () << std::endl;
84
+ exit (0 );
57
85
}
58
86
59
- if (filepath.empty ()) {
60
- std::cerr << USAGE << std::endl;
61
- return 1 ;
62
- }
87
+ const auto filepath = args[" filepath" ].as <std::string>();
63
88
64
89
bool is_file = std::filesystem::is_regular_file (filepath);
65
90
bool is_cpp_file = std::filesystem::path (filepath).extension ().string () == " .cpp" ;
66
91
67
92
// Inform the Rerun Viewer that we do not support that kind of file.
68
- if (!is_file || is_cpp_file) {
93
+ if (!is_file || ! is_cpp_file) {
69
94
return rerun::EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE;
70
95
}
71
96
@@ -75,12 +100,27 @@ int main(int argc, char* argv[]) {
75
100
76
101
std::string text = " ## Some C++ code\n ```cpp\n " + body.str () + " \n ```\n " ;
77
102
78
- const auto rec = rerun::RecordingStream (" rerun_example_external_data_loader" , recording_id);
103
+ auto application_id = std::string_view (" rerun_example_external_data_loader" );
104
+ if (args.count (" application-id" )) {
105
+ application_id = args[" application-id" ].as <std::string>();
106
+ }
107
+ auto recording_id = std::string_view ();
108
+ if (args.count (" recording-id" )) {
109
+ recording_id = args[" recording-id" ].as <std::string>();
110
+ }
111
+ const auto rec = rerun::RecordingStream (application_id, recording_id);
79
112
// The most important part of this: log to standard output so the Rerun Viewer can ingest it!
80
113
rec.to_stdout ().exit_on_failure ();
81
114
82
- rec.log_timeless (
83
- filepath,
115
+ set_time_from_args (rec, args);
116
+
117
+ auto entity_path = std::string (filepath);
118
+ if (args.count (" entity-path-prefix" )) {
119
+ entity_path = args[" entity-path-prefix" ].as <std::string>() + " /" + filepath;
120
+ }
121
+ rec.log_with_timeless (
122
+ entity_path,
123
+ args[" timeless" ].as <bool >(),
84
124
rerun::TextDocument (text).with_media_type (rerun::MediaType::markdown ())
85
125
);
86
126
}
0 commit comments