Commit 02eec9c9 authored by Nghia Truong's avatar Nghia Truong

ENH: Enhance the on-screen text status feature

Implement a second text status, allowing user to display custom information on screen.
parent 8441d585
......@@ -20,81 +20,169 @@
=========================================================================*/
#include "imstkSimulationManager.h"
#include "imstkTetrahedralMesh.h"
#include "imstkMeshIO.h"
#include "imstkSceneObject.h"
#include "imstkDebugGeometry.h"
#include "imstkAPIUtilities.h"
#include "imstkSurfaceMesh.h"
#include <memory>
#include "imstkVTKViewer.h"
#include "imstkVTKTextStatusManager.h"
#include <thread>
#include <chrono>
using namespace imstk;
///
/// \brief This example demonstrates the debug rendering
///
int main()
std::shared_ptr<DebugRenderGeometry>
addPointsDebugRendering(const std::shared_ptr<Scene>& scene)
{
auto sdk = std::make_shared<SimulationManager>();
auto scene = sdk->createNewScene("DebugRendering");
scene->getCamera()->setPosition(0, 2.0, 15.0);
auto debugPoints = std::make_shared<DebugRenderPoints>("Debug Points");
auto material = std::make_shared<RenderMaterial>();
material->setDebugColor(Color::Blue);
debugPoints->setRenderMaterial(material);
scene->addDebugGeometry(debugPoints);
// Create debug triangles
auto debugTriangleGeo = std::make_shared<DebugRenderTriangles>("debugtriangles", 9);
StdVectorOfVec3d triVerts;
triVerts.push_back(Vec3d(0., 0., 0.));
triVerts.push_back(Vec3d(0., 10., 0.));
triVerts.push_back(Vec3d(0., 0., 10.));
triVerts.push_back(Vec3d(0., 0., 0.));
triVerts.push_back(Vec3d(10., 0., 0.));
triVerts.push_back(Vec3d(0., 0., 10.));
return std::dynamic_pointer_cast<DebugRenderGeometry>(debugPoints);
}
triVerts.push_back(Vec3d(0., 0., 0.));
triVerts.push_back(Vec3d(10., 0., 0.));
triVerts.push_back(Vec3d(0., 10., 0.));
std::shared_ptr<DebugRenderGeometry>
addLinesDebugRendering(const std::shared_ptr<Scene>& scene)
{
auto debugLines = std::make_shared<DebugRenderLines>("Debug Lines");
auto material = std::make_shared<RenderMaterial>();
material->setBackFaceCulling(false);
material->setDebugColor(Color::Green);
material->setLineWidth(2.0);
debugLines->setRenderMaterial(material);
scene->addDebugGeometry(debugLines);
debugTriangleGeo->setVertexData(triVerts);
return std::dynamic_pointer_cast<DebugRenderGeometry>(debugLines);
}
auto material = std::make_shared<RenderMaterial>();
std::shared_ptr<DebugRenderGeometry>
addTrianglesDebugRendering(const std::shared_ptr<Scene>& scene)
{
auto debugTriangles = std::make_shared<DebugRenderTriangles>("Debug Triangles");
auto material = std::make_shared<RenderMaterial>();
material->setBackFaceCulling(false);
material->setDebugColor(Color::Red);
material->setDisplayMode(RenderMaterial::DisplayMode::WIREFRAME_SURFACE);
debugTriangleGeo->setRenderMaterial(material);
scene->addDebugGeometry(debugTriangleGeo);
// Create debug Lines
auto debugLinesGeo = std::make_shared<DebugRenderLines>("debugLines");
StdVectorOfVec3d linesVerts;
linesVerts.push_back(Vec3d(15, 0, 0));
linesVerts.push_back(Vec3d(100, 0, 0));
debugTriangles->setRenderMaterial(material);
scene->addDebugGeometry(debugTriangles);
linesVerts.push_back(Vec3d(0, 15, 0));
linesVerts.push_back(Vec3d(0, 100, 0));
linesVerts.push_back(Vec3d(0, 0, 15));
linesVerts.push_back(Vec3d(0, 0, 100));
debugLinesGeo->setVertexData(linesVerts);
auto materialLines = std::make_shared<RenderMaterial>();
materialLines->setBackFaceCulling(false);
materialLines->setDebugColor(Color::Green);
materialLines->setLineWidth(2.0);
debugLinesGeo->setRenderMaterial(materialLines);
scene->addDebugGeometry(debugLinesGeo);
return std::dynamic_pointer_cast<DebugRenderGeometry>(debugTriangles);
}
// Add light
auto light = std::make_shared<DirectionalLight>("light");
light->setFocalPoint(Vec3d(5, -8, -5));
light->setIntensity(1);
scene->addLight(light);
Vec3d
getRandomPositions(double radius)
{
return radius * Vec3d(2.0 * static_cast<double>(rand()) / static_cast<double>(RAND_MAX) - 1.0,
2.0 * static_cast<double>(rand()) / static_cast<double>(RAND_MAX) - 1.0,
2.0 * static_cast<double>(rand()) / static_cast<double>(RAND_MAX) - 1.0);
}
// Run the simulation
///
/// \brief This example demonstrates debug rendering in iMSTK
///
int
main()
{
// SDK and Scene
auto sdk = std::make_shared<SimulationManager>();
auto scene = sdk->createNewScene("Debug rendering example");
sdk->setActiveScene(scene);
sdk->startSimulation(SimulationStatus::PAUSED);
// Get the VTKViewer
auto viewer = std::dynamic_pointer_cast<VTKViewer>(sdk->getViewer());
viewer->getVtkRenderWindow()->SetSize(1920, 1080);
auto statusManager = viewer->getTextStatusManager();
statusManager->setStatusFontSize(VTKTextStatusManager::Custom, 30);
statusManager->setStatusFontColor(VTKTextStatusManager::Custom, Color::Orange);
// Get VTK Renderer
auto renderer = std::dynamic_pointer_cast<VTKRenderer>(viewer->getActiveRenderer());
LOG_IF(FATAL, (!renderer)) << "Invalid renderer: Only VTKRenderer is supported for debug rendering";
auto debugPoints = addPointsDebugRendering(scene);
auto debugLines = addLinesDebugRendering(scene);
auto debugTriangles = addTrianglesDebugRendering(scene);
int mode = 0; // 0: add point, 1: add line, 2: add triangle
int count = 0; // The number of times cycling between modes
auto updateFunc =
[&](Module*) {
if (count > 5)
{
count = 0;
debugPoints->clear();
debugLines->clear();
debugTriangles->clear();
}
if (mode % 3 == 0)
{
debugPoints->appendVertex(getRandomPositions(15.0));
}
else if (mode % 3 == 1)
{
auto p = getRandomPositions(50.0);
auto shift = getRandomPositions(1.0);
debugLines->appendVertex(p + shift);
debugLines->appendVertex(-p + shift);
}
else
{
auto shift = getRandomPositions(10.0);
debugTriangles->appendVertex(getRandomPositions(5.0) + shift);
debugTriangles->appendVertex(getRandomPositions(5.0) + shift);
debugTriangles->appendVertex(getRandomPositions(5.0) + shift);
mode = -1;
++count;
}
++mode;
debugPoints->turnDataModifiedFlagON();
debugLines->turnDataModifiedFlagON();
debugTriangles->turnDataModifiedFlagON();
// Must call to update render data
for (auto& delegate : renderer->getDebugRenderDelegates())
{
delegate->updateDataSource();
}
statusManager->setCustomStatus("Primatives: " +
std::to_string(debugPoints->getNumVertices()) + " (points) | " +
std::to_string(debugLines->getNumVertices() / 2) + " (lines) | " +
std::to_string(debugTriangles->getNumVertices() / 3) + " (triangles)"
);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
};
sdk->getSceneManager(scene)->setPostUpdateCallback(updateFunc);
// Set Camera configuration
auto cam = scene->getCamera();
cam->setPosition(Vec3d(0, 0, 50));
cam->setFocalPoint(Vec3d(0, 0, 0));
// Light
{
auto light = std::make_shared<DirectionalLight>("Light 1");
light->setFocalPoint(Vec3d(-1, -1, -1));
light->setIntensity(1);
scene->addLight(light);
}
{
auto light = std::make_shared<DirectionalLight>("Light 2");
light->setFocalPoint(Vec3d(1, -1, -1));
light->setIntensity(1);
scene->addLight(light);
}
// Run
sdk->startSimulation(SimulationStatus::RUNNING);
return 0;
}
......@@ -26,6 +26,7 @@
#include "imstkAPIUtilities.h"
#include "imstkPlane.h"
#include "imstkSphere.h"
#include "imstkVTKTextStatusManager.h"
#include "Fluid.hpp"
#include "Solid.hpp"
......@@ -36,25 +37,26 @@ using namespace imstk;
/// \brief Usage: ./SPHFluid [threads=<num_threads>] [radius=<particle_radius>]
/// \brief Example: ./SPHFluid threads=8 radius=0.01
///
int main(int argc, char* argv[])
int
main(int argc, char* argv[])
{
// SimulationManager must be created first
auto sdk = std::make_shared<SimulationManager>();
int threads = -1;
int threads = -1;
double particleRadius = 0.1;
// Parse command line arguments
for (int i = 1; i < argc; ++i)
{
auto param = std::string(argv[i]);
if (param.find("threads") == 0 &&
param.find_first_of("=") != std::string::npos)
if (param.find("threads") == 0
&& param.find_first_of("=") != std::string::npos)
{
threads = std::stoi(param.substr(param.find_first_of("=") + 1));
}
else if (param.find("radius") == 0 &&
param.find_first_of("=") != std::string::npos)
else if (param.find("radius") == 0
&& param.find_first_of("=") != std::string::npos)
{
particleRadius = std::stod(param.substr(param.find_first_of("=") + 1));
LOG(INFO) << "Particle radius: " << particleRadius;
......@@ -76,9 +78,23 @@ int main(int argc, char* argv[])
auto scene = sdk->createNewScene("SPH Fluid");
// Get the VTKViewer
auto viewer = std::dynamic_pointer_cast<VTKViewer>(sdk->getViewer());
viewer->getVtkRenderWindow()->SetSize(1920, 1080);
auto statusManager = viewer->getTextStatusManager();
statusManager->setStatusFontSize(VTKTextStatusManager::Custom, 30);
statusManager->setStatusFontColor(VTKTextStatusManager::Custom, Color::Red);
// Generate fluid and solid objects
auto fluidObj = generateFluid(scene, particleRadius);
auto solids = generateSolids(scene);
auto solids = generateSolids(scene);
sdk->getSceneManager(scene)->setPostUpdateCallback([&](Module*) {
statusManager->setCustomStatus("Number of particles: " +
std::to_string(fluidObj->getSPHModel()->getState().getNumParticles()) +
"\nNumber of solids: " + std::to_string(solids.size()));
});
// Collision between fluid and solid objects
auto colGraph = scene->getCollisionGraph();
......
......@@ -3,12 +3,14 @@
#-----------------------------------------------------------------------------
set(VTK_H_FILES
VTKRenderer/imstkVTKTextStatusManager.h
VTKRenderer/imstkVTKInteractorStyle.h
VTKRenderer/imstkVTKScreenCaptureUtility.h
VTKRenderer/imstkVTKViewer.h
VTKRenderer/imstkOpenVRCommand.h)
set(VTK_CPP_FILES
VTKRenderer/imstkVTKTextStatusManager.cpp
VTKRenderer/imstkVTKInteractorStyle.cpp
VTKRenderer/imstkVTKScreenCaptureUtility.cpp
VTKRenderer/imstkVTKViewer.cpp
......@@ -63,7 +65,7 @@ imstk_add_library( SimulationManager
Devices
Collision
)
#-----------------------------------------------------------------------------
# Testing
#-----------------------------------------------------------------------------
......
......@@ -22,6 +22,7 @@
// imstk
#include "imstkVTKInteractorStyle.h"
#include "imstkSimulationManager.h"
#include "imstkVTKTextStatusManager.h"
// vtk
#include "vtkObjectFactory.h"
......@@ -30,24 +31,18 @@
#include "vtkRenderer.h"
#include "vtkCamera.h"
#include "vtkTextActor.h"
#include "vtkTextProperty.h"
namespace imstk
{
VTKInteractorStyle::VTKInteractorStyle()
{
m_targetMS = 0.0; // 0 for no wait time
m_displayFps = false;
m_textStatusManager = std::make_shared<VTKTextStatusManager>(this);
m_lastFpsUpdate = std::chrono::high_resolution_clock::now();
m_lastFps = 60.0;
m_fpsActor = vtkTextActor::New();
m_fpsActor->GetTextProperty()->SetFontSize(60);
m_fpsActor->SetVisibility(m_displayFps);
}
VTKInteractorStyle::~VTKInteractorStyle()
{
m_fpsActor->Delete();
this->SetReferenceCount(0);
}
......@@ -57,23 +52,22 @@ VTKInteractorStyle::SetCurrentRenderer(vtkRenderer* ren)
// Remove actor if previous renderer
if (this->CurrentRenderer)
{
this->CurrentRenderer->RemoveActor2D(m_fpsActor);
for (int i = 0; i < VTKTextStatusManager::NumStatusTypes; ++i)
{
this->CurrentRenderer->RemoveActor2D(m_textStatusManager->getTextActor(i));
}
}
// Set new current renderer
vtkBaseInteractorStyle::SetCurrentRenderer(ren);
// Add actor to current renderer
this->CurrentRenderer->AddActor2D(m_fpsActor);
for (int i = 0; i < VTKTextStatusManager::NumStatusTypes; ++i)
{
this->CurrentRenderer->AddActor2D(m_textStatusManager->getTextActor(i));
}
}
// Cross-platform sprintf
#if defined(_WIN32) || defined(_WIN64)
# define IMSTK_SPRINT sprintf_s
#else
# define IMSTK_SPRINT sprintf
#endif
void
VTKInteractorStyle::OnTimer()
{
......@@ -88,56 +82,39 @@ VTKInteractorStyle::OnTimer()
// Reset camera clipping range
this->CurrentRenderer->ResetCameraClippingRange();
// Update framerate value display
auto now = std::chrono::high_resolution_clock::now();
double fps = 1e6 / (double)std::chrono::duration_cast<std::chrono::microseconds>(now - m_pre).count();
fps = 0.1 * fps + 0.9 * m_lastFps;
m_lastFps = fps;
int t = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_lastFpsUpdate).count();
if (t > 250) //wait 250ms before updating displayed value
if (m_displayFps)
{
std::string fpsVisualStr = "V: " + std::to_string((int)fps);
std::string fpsPhysicalStr;
if (m_simManager->getStatus() != SimulationStatus::PAUSED)
// Update framerate value display
auto now = std::chrono::high_resolution_clock::now();
double visualFPS = 1e6 / static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(now - m_pre).count());
visualFPS = 0.1 * visualFPS + 0.9 * m_lastFps;
m_lastFps = visualFPS;
int t = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(now - m_lastFpsUpdate).count());
if (t > 250) //wait 250ms before updating displayed value
{
char buff[32];
auto fps = m_simManager->getActiveScene()->getFPS();
if (fps < 4.0)
double physicalFPS;
if (m_simManager->getStatus() != SimulationStatus::PAUSED)
{
IMSTK_SPRINT(buff, "%.2f", fps);
physicalFPS = m_simManager->getActiveScene()->getFPS();
}
else
{
IMSTK_SPRINT(buff, "%d", static_cast<int>(fps));
physicalFPS = -1.0; // negative value means paused
}
fpsPhysicalStr = "P: " + std::string(buff);
}
else
{
fpsPhysicalStr = "P: PAUSED";
m_textStatusManager->setFPS(visualFPS, physicalFPS);
m_lastFpsUpdate = now;
}
m_fpsActor->SetInput((fpsVisualStr + std::string(" | ") + fpsPhysicalStr).c_str());
m_lastFpsUpdate = now;
m_pre = now;
}
m_pre = now;
// Render
this->Interactor->Render();
m_post = std::chrono::high_resolution_clock::now();
// Plan next render
auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(m_post - m_pre).count();
if (dt < m_targetMS)
{
this->Interactor->CreateOneShotTimer(m_targetMS - dt);
}
else
{
this->Interactor->CreateOneShotTimer(1);
}
this->Interactor->CreateOneShotTimer(0);
// Call custom behavior
if (m_onTimerFunction)
......@@ -178,14 +155,14 @@ VTKInteractorStyle::OnChar()
// Launch simulation if inactive
if (status == SimulationStatus::INACTIVE)
{
m_fpsActor->SetVisibility(m_displayFps);
m_textStatusManager->setStatusVisibility(VTKTextStatusManager::FPS, m_displayFps);
m_simManager->startSimulation(SimulationStatus::RUNNING);
}
}
else if (status != SimulationStatus::INACTIVE &&
(key == 'q' || key == 'Q' || key == 'e' || key == 'E')) // end Simulation
{
m_fpsActor->VisibilityOff();
m_textStatusManager->setStatusVisibility(VTKTextStatusManager::FPS, false);
//m_simManager->endSimulation();
}
else if (key == 'd' || key == 'D') // switch rendering mode
......@@ -206,7 +183,7 @@ VTKInteractorStyle::OnChar()
else if (key == 'p' || key == 'P') // switch framerate display
{
m_displayFps = !m_displayFps;
m_fpsActor->SetVisibility(m_displayFps);
m_textStatusManager->setStatusVisibility(VTKTextStatusManager::FPS, m_displayFps);
this->Interactor->Render();
}
else if (key == 'r' || key == 'R')
......
......@@ -29,12 +29,11 @@
#include "imstkInteractorStyle.h"
#include "vtkInteractorStyleTrackballCamera.h"
class vtkTextActor;
namespace imstk
{
class SimulationManager;
class VTKTextStatusManager;
/// Base class of the vtk interactor style used
using vtkBaseInteractorStyle = vtkInteractorStyleTrackballCamera;
......@@ -46,10 +45,10 @@ using vtkBaseInteractorStyle = vtkInteractorStyleTrackballCamera;
class VTKInteractorStyle : public vtkBaseInteractorStyle, public InteractorStyle
{
public:
vtkTypeMacro(VTKInteractorStyle, vtkBaseInteractorStyle);
vtkTypeMacro(VTKInteractorStyle, vtkBaseInteractorStyle)
VTKInteractorStyle();
virtual ~VTKInteractorStyle();
virtual ~VTKInteractorStyle() override;
///
/// \brief Set current renderer
......@@ -114,21 +113,32 @@ public:
///
/// \brief Not implemented
///
virtual void OnFourthButtonDown(){};
virtual void OnFifthButtonDown(){};
virtual void OnFourthButtonUp(){};
virtual void OnFifthButtonUp(){};
virtual void OnFourthButtonDown() override {}
virtual void OnFifthButtonDown() override {}
virtual void OnFourthButtonUp() override {}
virtual void OnFifthButtonUp() override {}
///
/// \brief Return the pointer to simulation manager
///
SimulationManager* getSimulationManager() { return m_simManager; }
///
/// \brief Return the window status handler
///
const std::shared_ptr<VTKTextStatusManager>& getTextStatusManager() { return m_textStatusManager; }
private:
friend class VTKViewer;
SimulationManager* m_simManager; ///> SimulationManager owning the current simulation being interacted with
double m_targetMS; ///> expected time between each render frame (in ms)
std::chrono::high_resolution_clock::time_point m_pre; ///> time point pre-rendering
std::chrono::high_resolution_clock::time_point m_post; ///> time point post-rendering
bool m_displayFps; ///> hide or display framerate
vtkTextActor* m_fpsActor; ///> text holding framerate to display
std::chrono::high_resolution_clock::time_point m_lastFpsUpdate; ///> time point for last framerate display update
double m_lastFps; ///> last framerate value used for moving average estimate
SimulationManager* m_simManager; ///> SimulationManager owning the current simulation being interacted with
std::chrono::high_resolution_clock::time_point m_pre; ///> time point pre-rendering
std::chrono::high_resolution_clock::time_point m_post; ///> time point post-rendering
std::chrono::high_resolution_clock::time_point m_lastFpsUpdate; ///> time point for last framerate display update
std::shared_ptr<VTKTextStatusManager> m_textStatusManager; ///> Handle text statuses, including fps status and custom text status
bool m_displayFps = false; ///> hide or display framerate
double m_lastFps; ///> last framerate value used for moving average estimate
};
} // imstk
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "imstkSimulationManager.h"
#include "imstkVTKTextStatusManager.h"
#include "imstkVTKInteractorStyle.h"
#include "imstkLogUtility.h"
#include "vtkTextActor.h"
#include "vtkTextProperty.h"
#include <algorithm>
#include <sstream>
#include <iostream>
namespace imstk
{
VTKTextStatusManager::VTKTextStatusManager(VTKInteractorStyle * const vtkInteractorStyle) :
m_vtkInteractorStyle(vtkInteractorStyle)
{
LOG_IF(FATAL, (!vtkInteractorStyle)) << "Invalid vtkInteractorStyle";
for (int i = 0; i < StatusType::NumStatusTypes; ++i)
{
m_StatusActors[i] = vtkTextActor::New();
m_StatusActors[i]->SetVisibility(false);
setStatusFontSize(static_cast<StatusType>(i), 60);
setStatusDisplayCorner(static_cast<StatusType>(i), static_cast<DisplayCorner>(i));
}
}
VTKTextStatusManager::~VTKTextStatusManager()
{
for (int i = 0; i < StatusType::NumStatusTypes; ++i)
{
m_StatusActors[i]->Delete();
}
}
vtkTextActor*
VTKTextStatusManager::getTextActor(const int i)
{
if (i < 0 || i >= StatusType::NumStatusTypes)
{
LOG(WARNING) << "Invalid text actor index";
return m_StatusActors[0];
}
return m_StatusActors[i];
}
void
VTKTextStatusManager::setStatusVisibility(const StatusType type, const bool bVisible)
{
m_StatusActors[type]->SetVisibility(bVisible);
}
void
VTKTextStatusManager::setStatusFontSize(const StatusType type, const int fontSize)
{
m_StatusFontSizes[type] = fontSize; // Store font size to compute and adjust text location later
m_StatusActors[type]->GetTextProperty()->SetFontSize(fontSize);
}
void
VTKTextStatusManager::setStatusFontColor(const StatusType type, const Color color)
{
m_StatusActors[type]->GetTextProperty()->SetColor(color.r, color.g, color.b);
}
void VTKTextStatusManager::setStatusDisplayCorner(const StatusType type, const DisplayCorner corner)
{
m_StatusDisplayCorners[type] = corner;
}
void VTKTextStatusManager::setFPS(const double visualFPS, const double physicsFPS)
{
std::string fpsVisualStr = "V: " + std::to_string(static_cast<int>(visualFPS));
std::string fpsPhysicalStr;
if (std::isnan(physicsFPS) || std::isinf(physicsFPS))
{
fpsPhysicalStr = "P: Inf";
}
else if (physicsFPS < 0)
{
fpsPhysicalStr = "P: PAUSED";
}
else
{
char buff[32];
(physicsFPS < 4.0) ? IMSTK_SPRINT(buff, "%.2f", physicsFPS) :
IMSTK_SPRINT(buff, "%d", static_cast<int>(physicsFPS));
fpsPhysicalStr = "P: " + std::string(buff);
}
std::string fpsString = fpsVisualStr + std::string(" | ") + fpsPhysicalStr;
auto fpsStatusCoordinate = computeStatusLocation(m_StatusDisplayCorners[StatusType::FPS],
m_StatusFontSizes[StatusType::FPS],
fpsString);
m_StatusActors[StatusType::FPS]->SetDisplayPosition(fpsStatusCoordinate[0], fpsStatusCoordinate[1]);
m_StatusActors[StatusType::FPS]->SetInput((fpsString).c_str());
}
void
VTKTextStatusManager::setCustomStatus(const std::string status)
{
auto customStatusCoordinate = computeStatusLocation(m_StatusDisplayCorners[StatusType::Custom],
m_StatusFontSizes[StatusType::Custom],
status);
m_StatusActors[StatusType::Custom]->SetInput(status.c_str());
m_StatusActors[StatusType::Custom]->SetDisplayPosition(customStatusCoordinate[0], customStatusCoordinate[1]);