Add ImGui OutlineViewer (#3220)
@@ -187,6 +187,7 @@ if (WITH_GUI)
|
||||
add_subdirectory(imgui)
|
||||
add_subdirectory(wpigui)
|
||||
add_subdirectory(glass)
|
||||
add_subdirectory(outlineviewer)
|
||||
endif()
|
||||
|
||||
if (WITH_CSCORE)
|
||||
|
||||
@@ -741,30 +741,20 @@ void glass::DisplayNetworkTables(NetworkTablesModel* model,
|
||||
ImGui::Columns();
|
||||
}
|
||||
|
||||
void NetworkTablesView::Display() {
|
||||
auto& storage = GetStorage();
|
||||
auto pTreeView =
|
||||
storage.GetBoolRef("tree", m_defaultFlags & NetworkTablesFlags_TreeView);
|
||||
auto pShowConnections = storage.GetBoolRef(
|
||||
"connections", m_defaultFlags & NetworkTablesFlags_ShowConnections);
|
||||
auto pShowFlags = storage.GetBoolRef(
|
||||
"flags", m_defaultFlags & NetworkTablesFlags_ShowFlags);
|
||||
auto pShowTimestamp = storage.GetBoolRef(
|
||||
"timestamp", m_defaultFlags & NetworkTablesFlags_ShowTimestamp);
|
||||
auto pCreateNoncanonicalKeys = storage.GetBoolRef(
|
||||
"createNonCanonical",
|
||||
m_defaultFlags & NetworkTablesFlags_CreateNoncanonicalKeys);
|
||||
|
||||
if (ImGui::BeginPopupContextItem()) {
|
||||
ImGui::MenuItem("Tree View", "", pTreeView);
|
||||
ImGui::MenuItem("Show Connections", "", pShowConnections);
|
||||
ImGui::MenuItem("Show Flags", "", pShowFlags);
|
||||
ImGui::MenuItem("Show Timestamp", "", pShowTimestamp);
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Allow creation of non-canonical keys", "",
|
||||
pCreateNoncanonicalKeys);
|
||||
|
||||
ImGui::EndPopup();
|
||||
void NetworkTablesFlagsSettings::Update() {
|
||||
if (!m_pTreeView) {
|
||||
auto& storage = GetStorage();
|
||||
m_pTreeView = storage.GetBoolRef(
|
||||
"tree", m_defaultFlags & NetworkTablesFlags_TreeView);
|
||||
m_pShowConnections = storage.GetBoolRef(
|
||||
"connections", m_defaultFlags & NetworkTablesFlags_ShowConnections);
|
||||
m_pShowFlags = storage.GetBoolRef(
|
||||
"flags", m_defaultFlags & NetworkTablesFlags_ShowFlags);
|
||||
m_pShowTimestamp = storage.GetBoolRef(
|
||||
"timestamp", m_defaultFlags & NetworkTablesFlags_ShowTimestamp);
|
||||
m_pCreateNoncanonicalKeys = storage.GetBoolRef(
|
||||
"createNonCanonical",
|
||||
m_defaultFlags & NetworkTablesFlags_CreateNoncanonicalKeys);
|
||||
}
|
||||
|
||||
m_flags &=
|
||||
@@ -772,11 +762,32 @@ void NetworkTablesView::Display() {
|
||||
NetworkTablesFlags_ShowFlags | NetworkTablesFlags_ShowTimestamp |
|
||||
NetworkTablesFlags_CreateNoncanonicalKeys);
|
||||
m_flags |=
|
||||
(*pTreeView ? NetworkTablesFlags_TreeView : 0) |
|
||||
(*pShowConnections ? NetworkTablesFlags_ShowConnections : 0) |
|
||||
(*pShowFlags ? NetworkTablesFlags_ShowFlags : 0) |
|
||||
(*pShowTimestamp ? NetworkTablesFlags_ShowTimestamp : 0) |
|
||||
(*pCreateNoncanonicalKeys ? NetworkTablesFlags_CreateNoncanonicalKeys
|
||||
: 0);
|
||||
DisplayNetworkTables(m_model, m_flags);
|
||||
(*m_pTreeView ? NetworkTablesFlags_TreeView : 0) |
|
||||
(*m_pShowConnections ? NetworkTablesFlags_ShowConnections : 0) |
|
||||
(*m_pShowFlags ? NetworkTablesFlags_ShowFlags : 0) |
|
||||
(*m_pShowTimestamp ? NetworkTablesFlags_ShowTimestamp : 0) |
|
||||
(*m_pCreateNoncanonicalKeys ? NetworkTablesFlags_CreateNoncanonicalKeys
|
||||
: 0);
|
||||
}
|
||||
|
||||
void NetworkTablesFlagsSettings::DisplayMenu() {
|
||||
if (!m_pTreeView) {
|
||||
return;
|
||||
}
|
||||
ImGui::MenuItem("Tree View", "", m_pTreeView);
|
||||
ImGui::MenuItem("Show Connections", "", m_pShowConnections);
|
||||
ImGui::MenuItem("Show Flags", "", m_pShowFlags);
|
||||
ImGui::MenuItem("Show Timestamp", "", m_pShowTimestamp);
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Allow creation of non-canonical keys", "",
|
||||
m_pCreateNoncanonicalKeys);
|
||||
}
|
||||
|
||||
void NetworkTablesView::Display() {
|
||||
m_flags.Update();
|
||||
if (ImGui::BeginPopupContextItem()) {
|
||||
m_flags.DisplayMenu();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
DisplayNetworkTables(m_model, m_flags.GetFlags());
|
||||
}
|
||||
|
||||
@@ -104,19 +104,39 @@ void DisplayNetworkTables(
|
||||
NetworkTablesModel* model,
|
||||
NetworkTablesFlags flags = NetworkTablesFlags_Default);
|
||||
|
||||
class NetworkTablesFlagsSettings {
|
||||
public:
|
||||
explicit NetworkTablesFlagsSettings(
|
||||
NetworkTablesFlags defaultFlags = NetworkTablesFlags_Default)
|
||||
: m_defaultFlags{defaultFlags}, m_flags{defaultFlags} {}
|
||||
|
||||
void Update();
|
||||
void DisplayMenu();
|
||||
|
||||
NetworkTablesFlags GetFlags() const { return m_flags; }
|
||||
|
||||
private:
|
||||
bool* m_pTreeView = nullptr;
|
||||
bool* m_pShowConnections = nullptr;
|
||||
bool* m_pShowFlags = nullptr;
|
||||
bool* m_pShowTimestamp = nullptr;
|
||||
bool* m_pCreateNoncanonicalKeys = nullptr;
|
||||
NetworkTablesFlags m_defaultFlags; // NOLINT
|
||||
NetworkTablesFlags m_flags; // NOLINT
|
||||
};
|
||||
|
||||
class NetworkTablesView : public View {
|
||||
public:
|
||||
explicit NetworkTablesView(
|
||||
NetworkTablesModel* model,
|
||||
NetworkTablesFlags defaultFlags = NetworkTablesFlags_Default)
|
||||
: m_model{model}, m_defaultFlags{defaultFlags}, m_flags{defaultFlags} {}
|
||||
: m_model{model}, m_flags{defaultFlags} {}
|
||||
|
||||
void Display() override;
|
||||
|
||||
private:
|
||||
NetworkTablesModel* m_model;
|
||||
NetworkTablesFlags m_defaultFlags;
|
||||
NetworkTablesFlags m_flags;
|
||||
NetworkTablesFlagsSettings m_flags;
|
||||
};
|
||||
|
||||
} // namespace glass
|
||||
|
||||
27
outlineviewer/.styleguide
Normal file
@@ -0,0 +1,27 @@
|
||||
cppHeaderFileInclude {
|
||||
\.h$
|
||||
\.inc$
|
||||
\.inl$
|
||||
}
|
||||
|
||||
cppSrcFileInclude {
|
||||
\.cpp$
|
||||
}
|
||||
|
||||
generatedFileExclude {
|
||||
src/main/native/resources/
|
||||
src/main/native/win/outlineviewer.ico
|
||||
src/main/native/mac/ov.icns
|
||||
}
|
||||
|
||||
repoRootNameOverride {
|
||||
outlineviewer
|
||||
}
|
||||
|
||||
includeOtherLibs {
|
||||
^GLFW
|
||||
^imgui
|
||||
^ntcore
|
||||
^wpi/
|
||||
^wpigui
|
||||
}
|
||||
28
outlineviewer/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
project(outlineviewer)
|
||||
|
||||
include(CompileWarnings)
|
||||
include(GenResources)
|
||||
include(LinkMacOSGUI)
|
||||
|
||||
configure_file(src/main/generate/WPILibVersion.cpp.in WPILibVersion.cpp)
|
||||
GENERATE_RESOURCES(src/main/native/resources generated/main/cpp OV ov outlineviewer_resources_src)
|
||||
|
||||
file(GLOB outlineviewer_src src/main/native/cpp/*.cpp ${CMAKE_CURRENT_BINARY_DIR}/WPILibVersion.cpp)
|
||||
|
||||
if (WIN32)
|
||||
set(outlineviewer_rc src/main/native/win/outlineviewer.rc)
|
||||
elseif(APPLE)
|
||||
set(MACOSX_BUNDLE_ICON_FILE ov.icns)
|
||||
set(APP_ICON_MACOSX src/main/native/mac/ov.icns)
|
||||
set_source_files_properties(${APP_ICON_MACOSX} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
endif()
|
||||
|
||||
add_executable(outlineviewer ${outlineviewer_src} ${outlineviewer_resources_src} ${outlineviewer_rc} ${APP_ICON_MACOSX})
|
||||
wpilib_link_macos_gui(outlineviewer)
|
||||
target_link_libraries(outlineviewer libglassnt libglass)
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(outlineviewer PROPERTIES WIN32_EXECUTABLE YES)
|
||||
elseif(APPLE)
|
||||
set_target_properties(outlineviewer PROPERTIES MACOSX_BUNDLE YES OUTPUT_NAME "OutlineViewer")
|
||||
endif()
|
||||
32
outlineviewer/Info.plist
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>OutlineViewer</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>outlineviewer</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>OutlineViewer</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>edu.wpi.first.tools.OutlineViewer</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>ov.icns</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2021</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2021</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.11</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
119
outlineviewer/build.gradle
Normal file
@@ -0,0 +1,119 @@
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {
|
||||
|
||||
description = "NetworkTables Viewer"
|
||||
|
||||
apply plugin: 'cpp'
|
||||
apply plugin: 'c'
|
||||
apply plugin: 'google-test-test-suite'
|
||||
apply plugin: 'visual-studio'
|
||||
apply plugin: 'edu.wpi.first.NativeUtils'
|
||||
|
||||
if (OperatingSystem.current().isWindows()) {
|
||||
apply plugin: 'windows-resources'
|
||||
}
|
||||
|
||||
ext {
|
||||
nativeName = 'outlineviewer'
|
||||
}
|
||||
|
||||
apply from: "${rootDir}/shared/resources.gradle"
|
||||
apply from: "${rootDir}/shared/config.gradle"
|
||||
|
||||
def wpilibVersionFileInput = file("src/main/generate/WPILibVersion.cpp.in")
|
||||
def wpilibVersionFileOutput = file("$buildDir/generated/main/cpp/WPILibVersion.cpp")
|
||||
|
||||
task generateCppVersion() {
|
||||
description = 'Generates the wpilib version class'
|
||||
group = 'WPILib'
|
||||
|
||||
outputs.file wpilibVersionFileOutput
|
||||
inputs.file wpilibVersionFileInput
|
||||
|
||||
if (wpilibVersioning.releaseMode) {
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
// We follow a simple set of checks to determine whether we should generate a new version file:
|
||||
// 1. If the release type is not development, we generate a new version file
|
||||
// 2. If there is no generated version number, we generate a new version file
|
||||
// 3. If there is a generated build number, and the release type is development, then we will
|
||||
// only generate if the publish task is run.
|
||||
doLast {
|
||||
def version = wpilibVersioning.version.get()
|
||||
println "Writing version ${version} to $wpilibVersionFileOutput"
|
||||
|
||||
if (wpilibVersionFileOutput.exists()) {
|
||||
wpilibVersionFileOutput.delete()
|
||||
}
|
||||
def read = wpilibVersionFileInput.text.replace('${wpilib_version}', version)
|
||||
wpilibVersionFileOutput.write(read)
|
||||
}
|
||||
}
|
||||
|
||||
gradle.taskGraph.addTaskExecutionGraphListener { graph ->
|
||||
def willPublish = graph.hasTask(publish)
|
||||
if (willPublish) {
|
||||
generateCppVersion.outputs.upToDateWhen { false }
|
||||
}
|
||||
}
|
||||
|
||||
def generateTask = createGenerateResourcesTask('main', 'OV', 'ov', project)
|
||||
|
||||
project(':').libraryBuild.dependsOn build
|
||||
tasks.withType(CppCompile) {
|
||||
dependsOn generateTask
|
||||
dependsOn generateCppVersion
|
||||
}
|
||||
|
||||
model {
|
||||
components {
|
||||
// By default, a development executable will be generated. This is to help the case of
|
||||
// testing specific functionality of the library.
|
||||
"${nativeName}"(NativeExecutableSpec) {
|
||||
baseName = 'outlineviewer'
|
||||
sources {
|
||||
cpp {
|
||||
source {
|
||||
srcDirs 'src/main/native/cpp', "$buildDir/generated/main/cpp"
|
||||
include '**/*.cpp'
|
||||
}
|
||||
exportedHeaders {
|
||||
srcDirs 'src/main/native/include'
|
||||
}
|
||||
}
|
||||
if (OperatingSystem.current().isWindows()) {
|
||||
rc {
|
||||
source {
|
||||
srcDirs 'src/main/native/win'
|
||||
include '*.rc'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
binaries.all {
|
||||
if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) {
|
||||
it.buildable = false
|
||||
return
|
||||
}
|
||||
lib project: ':glass', library: 'glassnt', linkage: 'static'
|
||||
lib project: ':glass', library: 'glass', linkage: 'static'
|
||||
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
|
||||
lib project: ':wpigui', library: 'wpigui', linkage: 'static'
|
||||
nativeUtils.useRequiredLibrary(it, 'imgui_static')
|
||||
if (it.targetPlatform.operatingSystem.isWindows()) {
|
||||
it.linker.args << 'Gdi32.lib' << 'Shell32.lib' << 'd3d11.lib' << 'd3dcompiler.lib'
|
||||
} else if (it.targetPlatform.operatingSystem.isMacOsX()) {
|
||||
it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore'
|
||||
} else {
|
||||
it.linker.args << '-lX11'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply from: 'publish.gradle'
|
||||
}
|
||||
96
outlineviewer/publish.gradle
Normal file
@@ -0,0 +1,96 @@
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
def baseArtifactId = 'OutlineViewer'
|
||||
def artifactGroupId = 'edu.wpi.first.tools'
|
||||
def zipBaseName = '_GROUP_edu_wpi_first_tools_ID_OutlineViewer_CLS'
|
||||
|
||||
def outputsFolder = file("$project.buildDir/outputs")
|
||||
|
||||
model {
|
||||
publishing {
|
||||
def outlineViewerTaskList = []
|
||||
$.components.each { component ->
|
||||
component.binaries.each { binary ->
|
||||
if (binary in NativeExecutableBinarySpec && binary.component.name.contains("outlineviewer")) {
|
||||
if (binary.buildable && binary.name.contains("Release")) {
|
||||
// We are now in the binary that we want.
|
||||
// This is the default application path for the ZIP task.
|
||||
def applicationPath = binary.executable.file
|
||||
def icon = file("$project.projectDir/src/main/native/mac/ov.icns")
|
||||
|
||||
// Create the macOS bundle.
|
||||
def bundleTask = project.tasks.create("bundleOutlineViewerOsxApp", Copy) {
|
||||
description("Creates a macOS application bundle for OutlineViewer")
|
||||
from(file("$project.projectDir/Info.plist"))
|
||||
into(file("$project.buildDir/outputs/bundles/OutlineViewer.app/Contents"))
|
||||
into("MacOS") { with copySpec { from binary.executable.file } }
|
||||
into("Resources") { with copySpec { from icon } }
|
||||
|
||||
doLast {
|
||||
if (project.hasProperty("developerID")) {
|
||||
// Get path to binary.
|
||||
exec {
|
||||
workingDir rootDir
|
||||
def args = [
|
||||
"sh",
|
||||
"-c",
|
||||
"codesign --force --strict --deep " +
|
||||
"--timestamp --options=runtime " +
|
||||
"--verbose -s ${project.findProperty("developerID")} " +
|
||||
"$project.buildDir/outputs/bundles/OutlineViewer.app/"
|
||||
]
|
||||
commandLine args
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the application path if we are creating a bundle.
|
||||
if (binary.targetPlatform.operatingSystem.isMacOsX()) {
|
||||
applicationPath = file("$project.buildDir/outputs/bundles")
|
||||
project.build.dependsOn bundleTask
|
||||
}
|
||||
|
||||
// Create the ZIP.
|
||||
def task = project.tasks.create("copyOutlineViewerExecutable", Zip) {
|
||||
description("Copies the OutlineViewer executable to the outputs directory.")
|
||||
destinationDirectory = outputsFolder
|
||||
|
||||
archiveBaseName = '_M_' + zipBaseName
|
||||
duplicatesStrategy = 'exclude'
|
||||
classifier = nativeUtils.getPublishClassifier(binary)
|
||||
|
||||
from(licenseFile) {
|
||||
into '/'
|
||||
}
|
||||
|
||||
from(applicationPath)
|
||||
into(nativeUtils.getPlatformPath(binary))
|
||||
}
|
||||
|
||||
if (binary.targetPlatform.operatingSystem.isMacOsX()) {
|
||||
bundleTask.dependsOn binary.tasks.link
|
||||
task.dependsOn(bundleTask)
|
||||
}
|
||||
|
||||
task.dependsOn binary.tasks.link
|
||||
outlineViewerTaskList.add(task)
|
||||
project.build.dependsOn task
|
||||
project.artifacts { task }
|
||||
addTaskToCopyAllOutputs(task)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publications {
|
||||
outlineViewer(MavenPublication) {
|
||||
outlineViewerTaskList.each { artifact it }
|
||||
|
||||
artifactId = baseArtifactId
|
||||
groupId = artifactGroupId
|
||||
version wpilibVersioning.version.get()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
outlineviewer/src/main/generate/WPILibVersion.cpp.in
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Autogenerated file! Do not manually edit this file. This version is regenerated
|
||||
* any time the publish task is run, or when this file is deleted.
|
||||
*/
|
||||
const char* GetWPILibVersion() {
|
||||
return "${wpilib_version}";
|
||||
}
|
||||
229
outlineviewer/src/main/native/cpp/main.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <imgui.h>
|
||||
#include <ntcore_cpp.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
#include "glass/Model.h"
|
||||
#include "glass/networktables/NetworkTables.h"
|
||||
#include "glass/networktables/NetworkTablesSettings.h"
|
||||
#include "glass/other/Log.h"
|
||||
|
||||
namespace gui = wpi::gui;
|
||||
|
||||
const char* GetWPILibVersion();
|
||||
|
||||
namespace ov {
|
||||
wpi::StringRef GetResource_ov_16_png();
|
||||
wpi::StringRef GetResource_ov_32_png();
|
||||
wpi::StringRef GetResource_ov_48_png();
|
||||
wpi::StringRef GetResource_ov_64_png();
|
||||
wpi::StringRef GetResource_ov_128_png();
|
||||
wpi::StringRef GetResource_ov_256_png();
|
||||
wpi::StringRef GetResource_ov_512_png();
|
||||
} // namespace ov
|
||||
|
||||
static std::unique_ptr<glass::NetworkTablesModel> gModel;
|
||||
static std::unique_ptr<glass::NetworkTablesSettings> gSettings;
|
||||
static glass::LogData gLog;
|
||||
static glass::NetworkTablesFlagsSettings gFlagsSettings;
|
||||
|
||||
static void NtInitialize() {
|
||||
// update window title when connection status changes
|
||||
auto inst = nt::GetDefaultInstance();
|
||||
auto poller = nt::CreateConnectionListenerPoller(inst);
|
||||
nt::AddPolledConnectionListener(poller, true);
|
||||
gui::AddEarlyExecute([inst, poller] {
|
||||
auto win = gui::GetSystemWindow();
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
bool timedOut;
|
||||
for (auto&& event : nt::PollConnectionListener(poller, 0, &timedOut)) {
|
||||
if ((nt::GetNetworkMode(inst) & NT_NET_MODE_SERVER) != 0) {
|
||||
// for server mode, just print number of clients connected
|
||||
wpi::SmallString<64> title;
|
||||
glfwSetWindowTitle(win, ("OutlineViewer - " +
|
||||
wpi::Twine{nt::GetConnections(inst).size()} +
|
||||
" Clients Connected")
|
||||
.toNullTerminatedStringRef(title)
|
||||
.data());
|
||||
} else if (event.connected) {
|
||||
wpi::SmallString<64> title;
|
||||
title = "OutlineViewer - Connected (";
|
||||
title += event.conn.remote_ip;
|
||||
title += ')';
|
||||
glfwSetWindowTitle(win, title.c_str());
|
||||
} else {
|
||||
glfwSetWindowTitle(win, "OutlineViewer - DISCONNECTED");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// handle NetworkTables log messages
|
||||
auto logPoller = nt::CreateLoggerPoller(inst);
|
||||
nt::AddPolledLogger(logPoller, NT_LOG_INFO, 100);
|
||||
gui::AddEarlyExecute([logPoller] {
|
||||
bool timedOut;
|
||||
for (auto&& msg : nt::PollLogger(logPoller, 0, &timedOut)) {
|
||||
const char* level = "";
|
||||
if (msg.level >= NT_LOG_CRITICAL) {
|
||||
level = "CRITICAL: ";
|
||||
} else if (msg.level >= NT_LOG_ERROR) {
|
||||
level = "ERROR: ";
|
||||
} else if (msg.level >= NT_LOG_WARNING) {
|
||||
level = "WARNING: ";
|
||||
}
|
||||
gLog.Append(wpi::Twine{level} + msg.message + wpi::Twine{" ("} +
|
||||
msg.filename + wpi::Twine{':'} + wpi::Twine{msg.line} +
|
||||
wpi::Twine{")\n"});
|
||||
}
|
||||
});
|
||||
|
||||
// NetworkTables table window
|
||||
gModel = std::make_unique<glass::NetworkTablesModel>();
|
||||
gui::AddEarlyExecute([] { gModel->Update(); });
|
||||
|
||||
// NetworkTables settings window
|
||||
gSettings = std::make_unique<glass::NetworkTablesSettings>();
|
||||
gui::AddEarlyExecute([] { gSettings->Update(); });
|
||||
}
|
||||
|
||||
static void DisplayGui() {
|
||||
ImGui::GetStyle().WindowRounding = 0;
|
||||
|
||||
// fill entire OS window with this window
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
int width, height;
|
||||
glfwGetWindowSize(gui::GetSystemWindow(), &width, &height);
|
||||
ImGui::SetNextWindowSize(ImVec2(width, height));
|
||||
|
||||
ImGui::Begin("Entries", nullptr,
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_MenuBar |
|
||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
gFlagsSettings.Update();
|
||||
|
||||
// can't create popups from within menu, so use flags
|
||||
bool settings = false;
|
||||
bool log = false;
|
||||
bool about = false;
|
||||
|
||||
// main menu
|
||||
ImGui::BeginMenuBar();
|
||||
gui::EmitViewMenu();
|
||||
if (ImGui::BeginMenu("View")) {
|
||||
gFlagsSettings.DisplayMenu();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Options")) {
|
||||
if (ImGui::MenuItem("Settings")) {
|
||||
settings = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Info")) {
|
||||
if (ImGui::MenuItem("Log")) {
|
||||
log = true;
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("About")) {
|
||||
about = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
|
||||
// settings popup
|
||||
if (settings) {
|
||||
ImGui::OpenPopup("Settings");
|
||||
}
|
||||
if (ImGui::BeginPopupModal("Settings", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (gSettings->Display()) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// log popup
|
||||
if (log) {
|
||||
ImGui::OpenPopup("Log");
|
||||
}
|
||||
if (ImGui::BeginPopupModal("Log", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (ImGui::Button("Close")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::BeginChild("Lines", ImVec2(width * 0.75f, height * 0.75f));
|
||||
glass::DisplayLog(&gLog, true);
|
||||
ImGui::EndChild();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// about popup
|
||||
if (about) {
|
||||
ImGui::OpenPopup("About");
|
||||
}
|
||||
if (ImGui::BeginPopupModal("About", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("OutlineViewer");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("v%s", GetWPILibVersion());
|
||||
if (ImGui::Button("Close")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// display table view
|
||||
glass::DisplayNetworkTables(gModel.get(), gFlagsSettings.GetFlags());
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int __stdcall WinMain(void* hInstance, void* hPrevInstance, char* pCmdLine,
|
||||
int nCmdShow) {
|
||||
#else
|
||||
int main() {
|
||||
#endif
|
||||
gui::CreateContext();
|
||||
glass::CreateContext();
|
||||
|
||||
gui::AddIcon(ov::GetResource_ov_16_png());
|
||||
gui::AddIcon(ov::GetResource_ov_32_png());
|
||||
gui::AddIcon(ov::GetResource_ov_48_png());
|
||||
gui::AddIcon(ov::GetResource_ov_64_png());
|
||||
gui::AddIcon(ov::GetResource_ov_128_png());
|
||||
gui::AddIcon(ov::GetResource_ov_256_png());
|
||||
gui::AddIcon(ov::GetResource_ov_512_png());
|
||||
|
||||
gui::ConfigurePlatformSaveFile("outlineviewer.ini");
|
||||
gui::AddInit(NtInitialize);
|
||||
|
||||
gui::AddLateExecute(DisplayGui);
|
||||
|
||||
gui::Initialize("OutlineViewer - DISCONNECTED", 1024, 768);
|
||||
gui::Main();
|
||||
|
||||
gModel.reset();
|
||||
gSettings.reset();
|
||||
|
||||
glass::DestroyContext();
|
||||
gui::DestroyContext();
|
||||
}
|
||||
BIN
outlineviewer/src/main/native/mac/ov.icns
Normal file
BIN
outlineviewer/src/main/native/resources/ov-128.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
outlineviewer/src/main/native/resources/ov-16.png
Normal file
|
After Width: | Height: | Size: 533 B |
BIN
outlineviewer/src/main/native/resources/ov-256.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
outlineviewer/src/main/native/resources/ov-32.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
outlineviewer/src/main/native/resources/ov-48.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
outlineviewer/src/main/native/resources/ov-512.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
outlineviewer/src/main/native/resources/ov-64.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
outlineviewer/src/main/native/win/outlineviewer.ico
Normal file
|
After Width: | Height: | Size: 71 KiB |
1
outlineviewer/src/main/native/win/outlineviewer.rc
Normal file
@@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON "outlineviewer.ico"
|
||||
@@ -29,6 +29,7 @@ include 'wpilibjExamples'
|
||||
include 'wpilibjIntegrationTests'
|
||||
include 'wpilibj'
|
||||
include 'glass'
|
||||
include 'outlineviewer'
|
||||
include 'simulation:gz_msgs'
|
||||
include 'simulation:frc_gazebo_plugins'
|
||||
include 'simulation:halsim_gazebo'
|
||||
|
||||