Below is sample code on how to create buttons using HPS API.
Sample code can be tested using hps_mfc_sandbox. Please replace the following functions in CHPSView.cpp.
Steps:
- Build and run hps_mfc_sandbox with sample code
- Click on UserCode3 (setup buttons)
- Load any model
- Click on button to activate corresponding operator
Notes:
We have an overload function to SetSubwindow(Rectangle const & position, IntRectangle const & offsets, Subwindow::Type type) which will make your buttons remain the same size.
The position values are still given as [-1,1] floats relative to the parent, but the offsets are pixel values relative to those.
Position gives a fractional location (where you measure from) and offset moves a fixed distance from that.For instance, you could make a subwindow that is always inset 25 pixels from its parent by specifying (-1,1,-1,1) & (25,-25,25,-25).
A 100x80 box stuck to the top-left corner would be (-1,-1,1,1) & (0, 100,-80,0).
A 10 pixel high along the top middle third of the parent would be (-0.333,0.333,1,1) & (0,0,-10,0).
Let’s say the two boxes are 50x50, 75 pixels from the bottom, and they are a bit left of center (let’s say centered about x = -0.1), one box could be (-0.1,-0.1,-1,-1) & (-50,0,75,126) and the other (-0.1,-0.1,-1,-1) & (0, 50, 75,125).
// Sample code to create two button on bottom of the scene
void CHPSView::OnUserCode2()
{
HPS::SegmentKey subWindowSegment = GetCanvas().GetFrontView().GetSegmentKey().Down("subwindow", true);
Point points[4] = { Point(0, 0, 0), Point(2, 0, 0), Point(2, 2, 0), Point(0, 2, 0) };
int faces[5] = { 4, 0, 3, 2, 1 };
subWindowSegment.GetTextAttributeControl().SetSize(6, HPS::Text::SizeUnits::Pixels).SetAlignment(Text::Alignment::Center);
subWindowSegment.GetVisibilityControl().SetFaces(true).SetEdges(true).SetLights(false);
HPS::SubwindowKit subwindowKit;
subwindowKit.SetSubwindow(HPS::Rectangle(0,0, -1, -1),HPS::IntRectangle(-150, 0, -25, 100), HPS::Subwindow::Type::Lightweight);
subWindowSegment.Subsegment("panOperator").InsertShell(4, points, 5, faces);
subWindowSegment.Subsegment("panOperator").GetMaterialMappingControl().SetFaceColor(HPS::RGBAColor(0, 1, 0));
subWindowSegment.Subsegment("panOperator").InsertText(HPS::Point(1, 1, 0), "PAN");
subWindowSegment.Subsegment("panOperator").SetSubwindow(subwindowKit);
HPS::SubwindowKit subwindowKit2;
subwindowKit2.SetSubwindow(HPS::Rectangle(-0, 0, -1, -1), HPS::IntRectangle(-75, 50, -25, 100), HPS::Subwindow::Type::Lightweight);
subWindowSegment.Subsegment("zoomOperator").InsertShell(4, points, 5, faces);
subWindowSegment.Subsegment("zoomOperator").GetMaterialMappingControl().SetFaceColor(HPS::RGBAColor(0, 1, 0));
subWindowSegment.Subsegment("zoomOperator").InsertText(HPS::Point(1, 1, 0), "ZOOM");
subWindowSegment.Subsegment("zoomOperator").SetSubwindow(subwindowKit2);
HPS::CameraKit cameraKit;
cameraKit.SetUpVector(Vector(0, 1, 0));
cameraKit.SetPosition(Point(0, 0, -10));
cameraKit.SetTarget(Point(0, 0, 0));
cameraKit.SetField(4, 4);
cameraKit.SetProjection(HPS::Camera::Projection::Orthographic);
subWindowSegment.SetCamera(cameraKit);
//GetCanvas().GetFrontView().GetOperatorControl().Pop();
//GetCanvas().GetFrontView().GetOperatorControl().Push(new MyOperatorControl(GetCanvas()), HPS::Operator::Priority::High);
GetCanvas().UpdateWithNotifier().Wait();
}
// Sample code to test if button was selected
void CHPSView::OnLButtonDown(UINT nFlags, CPoint point)
{
Point pixelPoint(point.x, point.y, 0);
Point windowPoint;
GetCanvas().GetWindowKey().ConvertCoordinate(HPS::Coordinate::Space::Pixel, pixelPoint, HPS::Coordinate::Space::Window, windowPoint);
GetCanvas().GetWindowKey().GetSelectionOptionsControl().SetLevel(HPS::Selection::Level::Entity); // choosing entity-level selection
GetCanvas().GetWindowKey().GetSelectionOptionsControl().SetProximity(0.01f);
GetCanvas().GetWindowKey().GetSelectionOptionsControl().SetAlgorithm(HPS::Selection::Algorithm::Analytic);
HPS::SelectionResults selectionResults;
size_t numSelectedItems = GetCanvas().GetWindowKey().GetSelectionControl().SelectByPoint( // this is the actual selection call
windowPoint, // the endpoint of the ray, typically the camera location
selectionResults);
// Check if button was button selected
HPS::SelectionResultsIterator iter = selectionResults.GetIterator();
while (iter.IsValid())
{
HPS::SelectionItem selectionItem = iter.GetItem();
Key key;
selectionItem.ShowSelectedItem(key); // 'key' is the HPS::Key of the selected item
if (key.Type() == HPS::Type::ShellKey)
{
// do something with this key
HPS::SegmentKey ownerSegment = key.Owner();
if (ownerSegment.Name() == "panOperator")
{
GetCanvas().GetFrontView().GetOperatorControl().Pop();
GetCanvas().GetFrontView().GetOperatorControl().Push(new HPS::PanOperator(MouseButtons::ButtonLeft()));
// Highlight button
// Please see Highlight section for sample code.
}
if (ownerSegment.Name() == "zoomOperator")
{
GetCanvas().GetFrontView().GetOperatorControl().Pop();
GetCanvas().GetFrontView().GetOperatorControl().Push(new HPS::ZoomOperator(MouseButtons::ButtonLeft()));
// Highlight button
// Please see Highlight section for sample code.
}
}
iter.Next();
}
SetCapture();
_canvas.GetWindowKey().GetEventDispatcher().InjectEvent(
BuildMouseEvent(HPS::MouseEvent::Action::ButtonDown, HPS::MouseButtons::ButtonLeft(), point, nFlags, 1));
CView::OnLButtonDown(nFlags, point);
}
3DF API
The same type of thing can be achieved using the 3DF API.
Here is sample code to setup button in the scene graph.
// Setup Buttons
void CSolidHoopsView::OnExtraSlot3() {
HPoint spts[4];
int facelist[5];
spts[0].x = -0.5f; spts[0].y = -0.5f; spts[0].z = 0.0f;
spts[1].x = 0.5f; spts[1].y = -0.5f; spts[1].z = 0.0f;
spts[2].x = 0.5f; spts[2].y = 0.5f; spts[2].z = 0.0f;
spts[3].x = -0.5f; spts[3].y = 0.5f; spts[3].z = 0.0f;
facelist[0] = 4; facelist[1] = 0; facelist[2] = 1; facelist[3] = 2;
facelist[4] = 3;
HC_Open_Segment_By_Key(m_pHView->GetOverwriteKey()); {
float position[] = { 0.0, 0.0, -5.0 };
float target[] = { 0.0, 0.0, 0.0 };
float up[] = { 0.0, 1.0, 0.0 };
float field_width = 10;
float field_height = 10;
HC_Open_Segment("subwindow"); {
HC_Set_Visibility("lights=off");
HC_Set_Camera(&position, &target, &up, field_width, field_height, "orthographic");
HC_Set_Window_Pattern("clear");
HC_Set_Visibility("faces=on,edges=on,text=on");
HC_Set_Selectability("geometry=on,windows=on");
HC_Open_Segment("panOperator"); {
HC_Insert_Shell(4, spts, 5, facelist);
HC_Insert_Text(0, 0, 0, "PAN");
HC_Translate_Object(0, -4.5f, 0);
} HC_Close_Segment();
HC_Open_Segment("orbitOperator"); {
HC_Translate_Object(1, -4.5f, 0);
HC_Insert_Text(0, 0, 0, "ORB");
HC_Insert_Shell(4, spts, 5, facelist);
} HC_Close_Segment();
} HC_Close_Segment();
} HC_Close_Segment();
m_pHView->Update();
}
In this case, the selection code is added to UserCode2 & 3.
This code checks to see if buttons are pressed and activates the operator.
void CSolidHoopsView::OnExtraSlot2()
{
int count;
HC_Open_Segment_By_Key(m_pHView->GetViewKey()); {
HC_Set_Selectability("everything = off,vertices = on!");
// HC_Set_Heuristics("related selection limit = 0");
// Let's make our first selection.
count = HC_Compute_Selection(".", "./scene/overwrite", "v", 0, -0.9f);
if (count > 0)
{
do {
char buffer[1024];
HC_Show_Selection_Pathname(buffer);
if (strstr(buffer, "panoperator"))
{
m_pHView->SetOperator(new HOpCameraPan(m_pHView))
}
} while (HC_Find_Related_Selection());
}
} HC_Close_Segment();
m_pHView->Update();
}
void CSolidHoopsView::OnExtraSlot3()
{
int count;
HC_Open_Segment_By_Key(m_pHView->GetViewKey()); {
HC_Set_Selectability("everything = off,vertices = on!");
// HC_Set_Heuristics("related selection limit = 0");
// Let's make our first selection.
count = HC_Compute_Selection(".", "./scene/overwrite", "v", -0.1, -0.9f);
if (count > 0)
{
do {
char buffer[1024];
HC_Show_Selection_Pathname(buffer);
if (strstr(buffer, "orbitoperator"))
{
m_pHView->SetOperator(new HOpCameraOrbit(m_pHView));
}
} while (HC_Find_Related_Selection());
}
} HC_Close_Segment();
m_pHView->Update();
}