How-to: Customize Navigation Cube Operator

Create a custom operator for Navigation cube operator to have an additional behavior when clicking Navigation cube.
For general information for custom operators:
https://docs.techsoft3d.com/hps/latest/prog_guide/0602_custom_operators.html

Instructions

  1. Create a custom operator by subclassing HPS::NavigationCubeOperator
  2. Implement OnMouseDown to processing input events.
  3. Push the custom operator to operator control in your view
// Show Navigation cube
GetCanvas().GetFrontView().GetNavigationCubeControl().SetVisibility(true); 
HPS::SegmentKey nav_cube_segment = GetCanvas().GetFrontView().GetNavigationCubeControl().GetSegmentKey();
// Set selectability so that the oeprator can select Navigation cube
nav_cube_segment.GetSelectabilityControl().SetFaces(HPS::Selectability::Value::On); 

GetCanvas().GetFrontView().GetOperatorControl().Push(new MyNavigationCubeOperator(GetCanvas().GetFrontView()), Operator::Priority::High);

Custom navigation cube operator sample

MyNavigationCubeOperator.h

#pragma once
#include "sprk.h"

class MyNavigationCubeOperator : public HPS::NavigationCubeOperator
{
public:
	MyNavigationCubeOperator(HPS::View);
	~MyNavigationCubeOperator();

	virtual bool OnMouseDown(HPS::MouseState const & in_state);
	bool IsEventRelevant(HPS::Point const & event_location, HPS::KeyPath const & key_path);

    HPS::View m_view;
	HPS::SelectionOptionsKit selection_options;
};

MyNavigationCubeOperator.cpp

#include "stdafx.h"
#include "MyNavigationCubeOperator.h"

MyNavigationCubeOperator::MyNavigationCubeOperator(HPS::View view)
	:NavigationCubeOperator(HPS::MouseButtons::ButtonLeft(), HPS::ModifierKeys())
{
	m_view = view;
	selection_options.SetRelatedLimit(0).SetLevel(HPS::Selection::Level::Entity).SetSorting(HPS::Selection::Sorting::ZSorting).SetProximity(0);
}

MyNavigationCubeOperator::~MyNavigationCubeOperator()
{}

bool MyNavigationCubeOperator::IsEventRelevant(HPS::Point const & event_location, HPS::KeyPath const & key_path)
{
	HPS::SegmentKey nav_cube_segment = m_view.GetNavigationCubeControl().GetSegmentKey();
	HPS::Rectangle subwindow;
	HPS::IntRectangle subwindow_offsets;
	HPS::Subwindow::Type subwindow_type;
	nav_cube_segment.GetSubwindowControl().ShowSubwindow(subwindow, subwindow_offsets, subwindow_type);

	if (subwindow_offsets != HPS::IntRectangle::Zero())
	{
		HPS::WindowPoint top_left(subwindow.left, subwindow.top);
		HPS::WindowPoint bottom_right(subwindow.right, subwindow.bottom);
		key_path.ConvertCoordinate(HPS::Coordinate::Space::Window, top_left, HPS::Coordinate::Space::Pixel, top_left);
		key_path.ConvertCoordinate(HPS::Coordinate::Space::Window, bottom_right, HPS::Coordinate::Space::Pixel, bottom_right);

		HPS::WindowPoint pixel_event_location;
		key_path.ConvertCoordinate(HPS::Coordinate::Space::Window, event_location, HPS::Coordinate::Space::Pixel, pixel_event_location);

		if (pixel_event_location.x < top_left.x + subwindow_offsets.left ||
			pixel_event_location.x > bottom_right.x + subwindow_offsets.right ||
			pixel_event_location.y < top_left.y - subwindow_offsets.top ||
			pixel_event_location.y > bottom_right.y - subwindow_offsets.bottom)
			return false;
	}
	else if (event_location.x < subwindow.left ||
		event_location.x > subwindow.right ||
		event_location.y < subwindow.bottom ||
		event_location.y > subwindow.top)
		return false;

	return true;
}

static float value = 1.0;
bool MyNavigationCubeOperator::OnMouseDown(HPS::MouseState const & in_state)
{
	if (!IsMouseTriggered(in_state))
		return false;

	HPS::KeyPath event_path(in_state.GetEventPath());
	HPS::Point inner_window_point;
	event_path.ConvertCoordinate(HPS::Coordinate::Space::Window, in_state.GetLocation(), HPS::Coordinate::Space::InnerWindow, inner_window_point);

	if (IsEventRelevant(inner_window_point, event_path))
	{
		HPS::SelectionResults selection_results;
		size_t count = in_state.GetEventSource().GetSelectionControl().SelectByPoint(in_state.GetLocation(), selection_options, selection_results);
		if (count > 0)
		{
			HPS::SelectionResultsIterator it = selection_results.GetIterator();
			while (it.IsValid())
			{
				HPS::ReferenceKey shell;
				HPS::KeyPath path;
				HPS::SelectionItem item = it.GetItem();
				item.ShowPath(path);
				HPS::Key const & front = path.Front();
				if (front.Type() == HPS::Type::ReferenceKey)
				{
					shell = (HPS::ReferenceKey)front;
					if (shell.Owner().Owner().Name() == "hps_navigation_cube")
					{
						// When Navigation cube is selected, do something
						if (value <= 0.0)
							value = 1.0;
						m_view.GetAttachedModel().GetSegmentKey().GetMaterialMappingControl().SetFaceAlpha(value);
						value -= 0.5;
						m_view.Update();
						break;
					}
				}
				it.Next();
			}
		}
	}
	return HPS::NavigationCubeOperator::OnMouseDown(in_state);
}