mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-19 13:40:49 +03:00
0032433: Visualization, TKService - introduce Wasm_Window implementing Aspect_Window interface using Emscripten SDK
Introduced Wasm_Window implementing Aspect_Window interface. Aspect_WindowInputListener has been extended by touch input callbacks (moved from AIS_ViewController), which now implements redirection of single taps to UpdateMouseClick(). AIS_ViewController::FetchNavigationKeys() now requests more frames even if Delta is zero, but navigation keys are pressed - indicated by a new flag AIS_WalkDelta::IsDefined(). Fixed missing implementation of Xw_Window::DisplayConnection() getter. The property has been moved to the base class Aspect_Window. Removed unused Aspect_Convert.hxx. DRAWEXE targeting Wasm: - added exposing of FS interface so that it is possible uploading/downloading files to/from emulated file system on JavaScript level; - added printer redirecting messages to Module.printMessage callback accepting message gravity; - Run_Appli() now skips std::cin when Module.noExitRuntime is set.
This commit is contained in:
@@ -28,7 +28,6 @@ if (NOT "${SOURCE_MAP_BASE}" STREQUAL "")
|
||||
endif()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s MODULARIZE=1")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORT_NAME='createOccViewerModule'")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap']")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/occt-webgl-viewer.js")
|
||||
|
||||
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})
|
||||
|
@@ -21,14 +21,12 @@
|
||||
|
||||
#include "WasmOcctView.h"
|
||||
|
||||
#include "WasmVKeys.h"
|
||||
#include "WasmOcctPixMap.h"
|
||||
|
||||
#include <AIS_Shape.hxx>
|
||||
#include <AIS_ViewCube.hxx>
|
||||
#include <Aspect_Handle.hxx>
|
||||
#include <Aspect_DisplayConnection.hxx>
|
||||
#include <Aspect_NeutralWindow.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Graphic3d_CubeMapPacked.hxx>
|
||||
@@ -36,6 +34,7 @@
|
||||
#include <Prs3d_DatumAspect.hxx>
|
||||
#include <Prs3d_ToolCylinder.hxx>
|
||||
#include <Prs3d_ToolDisk.hxx>
|
||||
#include <Wasm_Window.hxx>
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
@@ -50,25 +49,6 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
EM_JS(int, jsCanvasGetWidth, (), {
|
||||
return Module.canvas.width;
|
||||
});
|
||||
|
||||
EM_JS(int, jsCanvasGetHeight, (), {
|
||||
return Module.canvas.height;
|
||||
});
|
||||
|
||||
EM_JS(float, jsDevicePixelRatio, (), {
|
||||
var aDevicePixelRatio = window.devicePixelRatio || 1;
|
||||
return aDevicePixelRatio;
|
||||
});
|
||||
|
||||
//! Return cavas size in pixels.
|
||||
static Graphic3d_Vec2i jsCanvasSize()
|
||||
{
|
||||
return Graphic3d_Vec2i (jsCanvasGetWidth(), jsCanvasGetHeight());
|
||||
}
|
||||
|
||||
//! Auxiliary wrapper for loading model.
|
||||
struct ModelAsyncLoader
|
||||
{
|
||||
@@ -199,7 +179,7 @@ void WasmOcctView::run()
|
||||
// ================================================================
|
||||
void WasmOcctView::initWindow()
|
||||
{
|
||||
myDevicePixelRatio = jsDevicePixelRatio();
|
||||
myDevicePixelRatio = emscripten_get_device_pixel_ratio();
|
||||
myCanvasId = THE_CANVAS_ID;
|
||||
const char* aTargetId = !myCanvasId.IsEmpty() ? myCanvasId.ToCString() : EMSCRIPTEN_EVENT_TARGET_WINDOW;
|
||||
const EM_BOOL toUseCapture = EM_TRUE;
|
||||
@@ -340,13 +320,8 @@ bool WasmOcctView::initViewer()
|
||||
}
|
||||
}
|
||||
|
||||
Handle(Aspect_NeutralWindow) aWindow = new Aspect_NeutralWindow();
|
||||
Graphic3d_Vec2i aWinSize = jsCanvasSize();
|
||||
if (aWinSize.x() < 10 || aWinSize.y() < 10)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("Warning: invalid canvas size"), Message_Warning);
|
||||
}
|
||||
aWindow->SetSize (aWinSize.x(), aWinSize.y());
|
||||
Handle(Wasm_Window) aWindow = new Wasm_Window (THE_CANVAS_ID);
|
||||
aWindow->Size (myWinSizeOld.x(), myWinSizeOld.y());
|
||||
|
||||
myTextStyle = new Prs3d_TextAspect();
|
||||
myTextStyle->SetFont (Font_NOF_ASCII_MONO);
|
||||
@@ -403,6 +378,24 @@ void WasmOcctView::initDemoScene()
|
||||
// Build with "--preload-file MySampleFile.brep" option to load some shapes here.
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Function : ProcessInput
|
||||
// Purpose :
|
||||
// ================================================================
|
||||
void WasmOcctView::ProcessInput()
|
||||
{
|
||||
if (!myView.IsNull())
|
||||
{
|
||||
// Queue onRedrawView()/redrawView callback to redraw canvas after all user input is flushed by browser.
|
||||
// Redrawing viewer on every single message would be a pointless waste of resources,
|
||||
// as user will see only the last drawn frame due to WebGL implementation details.
|
||||
if (++myUpdateRequests == 1)
|
||||
{
|
||||
emscripten_async_call (onRedrawView, this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Function : UpdateView
|
||||
// Purpose :
|
||||
@@ -412,22 +405,8 @@ void WasmOcctView::UpdateView()
|
||||
if (!myView.IsNull())
|
||||
{
|
||||
myView->Invalidate();
|
||||
updateView();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Function : updateView
|
||||
// Purpose :
|
||||
// ================================================================
|
||||
void WasmOcctView::updateView()
|
||||
{
|
||||
if (!myView.IsNull())
|
||||
{
|
||||
if (++myUpdateRequests == 1)
|
||||
{
|
||||
emscripten_async_call (onRedrawView, this, 0);
|
||||
}
|
||||
// queue next onRedrawView()/redrawView()
|
||||
ProcessInput();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,14 +431,6 @@ void WasmOcctView::handleViewRedraw (const Handle(AIS_InteractiveContext)& theCt
|
||||
{
|
||||
myUpdateRequests = 0;
|
||||
AIS_ViewController::handleViewRedraw (theCtx, theView);
|
||||
|
||||
for (NCollection_DataMap<unsigned int, Aspect_VKey>::Iterator aNavKeyIter (myNavKeyMap);
|
||||
!myToAskNextFrame && aNavKeyIter.More(); aNavKeyIter.Next())
|
||||
{
|
||||
const Aspect_VKey aVKey = aNavKeyIter.Key() & ~Aspect_VKeyFlags_ALL;
|
||||
myToAskNextFrame = myKeys.IsKeyDown (aVKey);
|
||||
}
|
||||
|
||||
if (myToAskNextFrame)
|
||||
{
|
||||
// ask more frames
|
||||
@@ -481,23 +452,21 @@ EM_BOOL WasmOcctView::onResizeEvent (int theEventType, const EmscriptenUiEvent*
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
Handle(Aspect_NeutralWindow) aWindow = Handle(Aspect_NeutralWindow)::DownCast (myView->Window());
|
||||
Graphic3d_Vec2i aWinSizeOld, aWinSizeNew (jsCanvasSize());
|
||||
if (aWinSizeNew.x() < 10 || aWinSizeNew.y() < 10)
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("Warning: invalid canvas size"), Message_Warning);
|
||||
}
|
||||
aWindow->Size (aWinSizeOld.x(), aWinSizeOld.y());
|
||||
const float aPixelRatio = jsDevicePixelRatio();
|
||||
if (aWinSizeNew != aWinSizeOld
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
|
||||
Graphic3d_Vec2i aWinSizeNew;
|
||||
aWindow->DoResize();
|
||||
aWindow->Size (aWinSizeNew.x(), aWinSizeNew.y());
|
||||
const float aPixelRatio = emscripten_get_device_pixel_ratio();
|
||||
if (aWinSizeNew != myWinSizeOld
|
||||
|| aPixelRatio != myDevicePixelRatio)
|
||||
{
|
||||
myWinSizeOld = aWinSizeNew;
|
||||
if (myDevicePixelRatio != aPixelRatio)
|
||||
{
|
||||
myDevicePixelRatio = aPixelRatio;
|
||||
initPixelScaleRatio();
|
||||
}
|
||||
aWindow->SetSize (aWinSizeNew.x(), aWinSizeNew.y());
|
||||
|
||||
myView->MustBeResized();
|
||||
myView->Invalidate();
|
||||
myView->Redraw();
|
||||
@@ -517,73 +486,8 @@ EM_BOOL WasmOcctView::onMouseEvent (int theEventType, const EmscriptenMouseEvent
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
Graphic3d_Vec2i aWinSize;
|
||||
myView->Window()->Size (aWinSize.x(), aWinSize.y());
|
||||
const Graphic3d_Vec2i aNewPos = convertPointToBacking (Graphic3d_Vec2i (theEvent->targetX, theEvent->targetY));
|
||||
Aspect_VKeyFlags aFlags = 0;
|
||||
if (theEvent->ctrlKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_CTRL; }
|
||||
if (theEvent->shiftKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_SHIFT; }
|
||||
if (theEvent->altKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_ALT; }
|
||||
if (theEvent->metaKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_META; }
|
||||
|
||||
const bool isEmulated = false;
|
||||
const Aspect_VKeyMouse aButtons = WasmVKeys_MouseButtonsFromNative (theEvent->buttons);
|
||||
switch (theEventType)
|
||||
{
|
||||
case EMSCRIPTEN_EVENT_MOUSEMOVE:
|
||||
{
|
||||
if ((aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
|
||||
|| aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
|
||||
&& PressedMouseButtons() == Aspect_VKeyMouse_NONE)
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
if (UpdateMousePosition (aNewPos, aButtons, aFlags, isEmulated))
|
||||
{
|
||||
updateView();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_MOUSEDOWN:
|
||||
case EMSCRIPTEN_EVENT_MOUSEUP:
|
||||
{
|
||||
if (aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
|
||||
|| aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
if (UpdateMouseButtons (aNewPos, aButtons, aFlags, isEmulated))
|
||||
{
|
||||
updateView();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_CLICK:
|
||||
case EMSCRIPTEN_EVENT_DBLCLICK:
|
||||
{
|
||||
if (aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
|
||||
|| aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_MOUSEENTER:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_MOUSELEAVE:
|
||||
{
|
||||
// there is no SetCapture() support, so that mouse unclick events outside canvas will not arrive,
|
||||
// so we have to forget current state...
|
||||
if (UpdateMouseButtons (aNewPos, Aspect_VKeyMouse_NONE, aFlags, isEmulated))
|
||||
{
|
||||
updateView();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return EM_TRUE;
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
|
||||
return aWindow->ProcessMouseEvent (*this, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
@@ -598,40 +502,8 @@ EM_BOOL WasmOcctView::onWheelEvent (int theEventType, const EmscriptenWheelEvent
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
Graphic3d_Vec2i aWinSize;
|
||||
myView->Window()->Size (aWinSize.x(), aWinSize.y());
|
||||
const Graphic3d_Vec2i aNewPos = convertPointToBacking (Graphic3d_Vec2i (theEvent->mouse.targetX, theEvent->mouse.targetY));
|
||||
if (aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
|
||||
|| aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
double aDelta = 0.0;
|
||||
switch (theEvent->deltaMode)
|
||||
{
|
||||
case DOM_DELTA_PIXEL:
|
||||
{
|
||||
aDelta = theEvent->deltaY / (5.0 * myDevicePixelRatio);
|
||||
break;
|
||||
}
|
||||
case DOM_DELTA_LINE:
|
||||
{
|
||||
aDelta = theEvent->deltaY * 8.0;
|
||||
break;
|
||||
}
|
||||
case DOM_DELTA_PAGE:
|
||||
{
|
||||
aDelta = theEvent->deltaY >= 0.0 ? 24.0 : -24.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (UpdateZoom (Aspect_ScrollDelta (aNewPos, -aDelta)))
|
||||
{
|
||||
updateView();
|
||||
}
|
||||
return EM_TRUE;
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
|
||||
return aWindow->ProcessWheelEvent (*this, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
@@ -640,90 +512,13 @@ EM_BOOL WasmOcctView::onWheelEvent (int theEventType, const EmscriptenWheelEvent
|
||||
// ================================================================
|
||||
EM_BOOL WasmOcctView::onTouchEvent (int theEventType, const EmscriptenTouchEvent* theEvent)
|
||||
{
|
||||
const double aClickTolerance = 5.0;
|
||||
if (myView.IsNull())
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
Graphic3d_Vec2i aWinSize;
|
||||
myView->Window()->Size (aWinSize.x(), aWinSize.y());
|
||||
bool hasUpdates = false;
|
||||
for (int aTouchIter = 0; aTouchIter < theEvent->numTouches; ++aTouchIter)
|
||||
{
|
||||
const EmscriptenTouchPoint& aTouch = theEvent->touches[aTouchIter];
|
||||
if (!aTouch.isChanged)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const Standard_Size aTouchId = (Standard_Size )aTouch.identifier;
|
||||
const Graphic3d_Vec2i aNewPos = convertPointToBacking (Graphic3d_Vec2i (aTouch.targetX, aTouch.targetY));
|
||||
switch (theEventType)
|
||||
{
|
||||
case EMSCRIPTEN_EVENT_TOUCHSTART:
|
||||
{
|
||||
if (aNewPos.x() >= 0 && aNewPos.x() < aWinSize.x()
|
||||
&& aNewPos.y() >= 0 && aNewPos.y() < aWinSize.y())
|
||||
{
|
||||
hasUpdates = true;
|
||||
AddTouchPoint (aTouchId, Graphic3d_Vec2d (aNewPos));
|
||||
myClickTouch.From.SetValues (-1.0, -1.0);
|
||||
if (myTouchPoints.Extent() == 1)
|
||||
{
|
||||
myClickTouch.From = Graphic3d_Vec2d (aNewPos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_TOUCHMOVE:
|
||||
{
|
||||
const int anOldIndex = myTouchPoints.FindIndex (aTouchId);
|
||||
if (anOldIndex != 0)
|
||||
{
|
||||
hasUpdates = true;
|
||||
UpdateTouchPoint (aTouchId, Graphic3d_Vec2d (aNewPos));
|
||||
if (myTouchPoints.Extent() == 1
|
||||
&& (myClickTouch.From - Graphic3d_Vec2d (aNewPos)).cwiseAbs().maxComp() > aClickTolerance)
|
||||
{
|
||||
myClickTouch.From.SetValues (-1.0, -1.0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_TOUCHEND:
|
||||
case EMSCRIPTEN_EVENT_TOUCHCANCEL:
|
||||
{
|
||||
if (RemoveTouchPoint (aTouchId))
|
||||
{
|
||||
if (myTouchPoints.IsEmpty()
|
||||
&& myClickTouch.From.minComp() >= 0.0)
|
||||
{
|
||||
if (myDoubleTapTimer.IsStarted()
|
||||
&& myDoubleTapTimer.ElapsedTime() <= myMouseDoubleClickInt)
|
||||
{
|
||||
myView->FitAll (0.01, false);
|
||||
myView->Invalidate();
|
||||
}
|
||||
else
|
||||
{
|
||||
myDoubleTapTimer.Stop();
|
||||
myDoubleTapTimer.Reset();
|
||||
myDoubleTapTimer.Start();
|
||||
SelectInViewer (Graphic3d_Vec2i (myClickTouch.From), AIS_SelectionScheme_Replace);
|
||||
}
|
||||
}
|
||||
hasUpdates = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasUpdates)
|
||||
{
|
||||
updateView();
|
||||
}
|
||||
return hasUpdates || !myTouchPoints.IsEmpty() ? EM_TRUE : EM_FALSE;
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
|
||||
return aWindow->ProcessTouchEvent (*this, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
@@ -775,35 +570,34 @@ EM_BOOL WasmOcctView::onKeyDownEvent (int theEventType, const EmscriptenKeyboard
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
const double aTimeStamp = EventTime();
|
||||
const Aspect_VKey aVKey = WasmVKeys_VirtualKeyFromNative (theEvent->keyCode);
|
||||
if (aVKey == Aspect_VKey_UNKNOWN)
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
if (theEvent->repeat == EM_TRUE)
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
|
||||
return aWindow->ProcessKeyEvent (*this, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : KeyDown
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void WasmOcctView::KeyDown (Aspect_VKey theKey,
|
||||
double theTime,
|
||||
double thePressure)
|
||||
{
|
||||
const unsigned int aModifOld = myKeys.Modifiers();
|
||||
AIS_ViewController::KeyDown (aVKey, aTimeStamp);
|
||||
AIS_ViewController::KeyDown (theKey, theTime, thePressure);
|
||||
|
||||
const unsigned int aModifNew = myKeys.Modifiers();
|
||||
if (aModifNew != aModifOld
|
||||
&& navigationKeyModifierSwitch (aModifOld, aModifNew, aTimeStamp))
|
||||
&& navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
|
||||
{
|
||||
// modifier key just pressed
|
||||
}
|
||||
|
||||
Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
|
||||
if (myNavKeyMap.Find (aVKey | myKeys.Modifiers(), anAction)
|
||||
if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
|
||||
&& anAction != Aspect_VKey_UNKNOWN)
|
||||
{
|
||||
AIS_ViewController::KeyDown (anAction, aTimeStamp);
|
||||
UpdateView();
|
||||
AIS_ViewController::KeyDown (anAction, theTime, thePressure);
|
||||
}
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
@@ -818,32 +612,36 @@ EM_BOOL WasmOcctView::onKeyUpEvent (int theEventType, const EmscriptenKeyboardEv
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
const double aTimeStamp = EventTime();
|
||||
const Aspect_VKey aVKey = WasmVKeys_VirtualKeyFromNative (theEvent->keyCode);
|
||||
if (aVKey == Aspect_VKey_UNKNOWN)
|
||||
{
|
||||
return EM_FALSE;
|
||||
}
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
|
||||
return aWindow->ProcessKeyEvent (*this, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : KeyUp
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void WasmOcctView::KeyUp (Aspect_VKey theKey,
|
||||
double theTime)
|
||||
{
|
||||
const unsigned int aModifOld = myKeys.Modifiers();
|
||||
AIS_ViewController::KeyUp (aVKey, aTimeStamp);
|
||||
AIS_ViewController::KeyUp (theKey, theTime);
|
||||
|
||||
Aspect_VKey anAction = Aspect_VKey_UNKNOWN;
|
||||
if (myNavKeyMap.Find (aVKey | myKeys.Modifiers(), anAction)
|
||||
if (myNavKeyMap.Find (theKey | myKeys.Modifiers(), anAction)
|
||||
&& anAction != Aspect_VKey_UNKNOWN)
|
||||
{
|
||||
AIS_ViewController::KeyUp (anAction, aTimeStamp);
|
||||
UpdateView();
|
||||
AIS_ViewController::KeyUp (anAction, theTime);
|
||||
processKeyPress (anAction);
|
||||
}
|
||||
|
||||
const unsigned int aModifNew = myKeys.Modifiers();
|
||||
if (aModifNew != aModifOld
|
||||
&& navigationKeyModifierSwitch (aModifOld, aModifNew, aTimeStamp))
|
||||
&& navigationKeyModifierSwitch (aModifOld, aModifNew, theTime))
|
||||
{
|
||||
// modifier key released
|
||||
}
|
||||
|
||||
return processKeyPress (aVKey | aModifNew) ? EM_TRUE : EM_FALSE;
|
||||
processKeyPress (theKey | aModifNew);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
@@ -136,9 +136,6 @@ private:
|
||||
//! Application event loop.
|
||||
void mainloop();
|
||||
|
||||
//! Request view redrawing.
|
||||
void updateView();
|
||||
|
||||
//! Flush events and redraw view.
|
||||
void redrawView();
|
||||
|
||||
@@ -146,25 +143,24 @@ private:
|
||||
virtual void handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
|
||||
const Handle(V3d_View)& theView) override;
|
||||
|
||||
//! Schedule processing of window input events with the next repaint event.
|
||||
virtual void ProcessInput() override;
|
||||
|
||||
//! Handle key down event.
|
||||
virtual void KeyDown (Aspect_VKey theKey,
|
||||
double theTime,
|
||||
double thePressure) override;
|
||||
|
||||
//! Handle key up event.
|
||||
virtual void KeyUp (Aspect_VKey theKey,
|
||||
double theTime) override;
|
||||
|
||||
//! Dump WebGL context information.
|
||||
void dumpGlInfo (bool theIsBasic);
|
||||
|
||||
//! Initialize pixel scale ratio.
|
||||
void initPixelScaleRatio();
|
||||
|
||||
//! Return point from logical units to backing store.
|
||||
Graphic3d_Vec2d convertPointToBacking (const Graphic3d_Vec2d& thePnt) const
|
||||
{
|
||||
return thePnt * myDevicePixelRatio;
|
||||
}
|
||||
|
||||
//! Return point from logical units to backing store.
|
||||
Graphic3d_Vec2i convertPointToBacking (const Graphic3d_Vec2i& thePnt) const
|
||||
{
|
||||
Graphic3d_Vec2d aPnt = Graphic3d_Vec2d (thePnt) * myDevicePixelRatio + Graphic3d_Vec2d (0.5);
|
||||
return Graphic3d_Vec2i (aPnt);
|
||||
}
|
||||
|
||||
//! @name Emscripten callbacks
|
||||
private:
|
||||
//! Window resize event.
|
||||
@@ -245,8 +241,7 @@ private:
|
||||
Handle(Prs3d_TextAspect) myTextStyle; //!< text style for OSD elements
|
||||
Handle(AIS_ViewCube) myViewCube; //!< view cube object
|
||||
TCollection_AsciiString myCanvasId; //!< canvas element id on HTML page
|
||||
Aspect_Touch myClickTouch; //!< single touch position for handling clicks
|
||||
OSD_Timer myDoubleTapTimer; //!< timer for handling double tap
|
||||
Graphic3d_Vec2i myWinSizeOld;
|
||||
float myDevicePixelRatio; //!< device pixel ratio for handling high DPI displays
|
||||
unsigned int myUpdateRequests; //!< counter for unhandled update requests
|
||||
|
||||
|
@@ -1,264 +0,0 @@
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of the examples of the Open CASCADE Technology software library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
|
||||
|
||||
#ifndef _WasmVKeys_HeaderFile
|
||||
#define _WasmVKeys_HeaderFile
|
||||
|
||||
#include <Aspect_VKey.hxx>
|
||||
|
||||
#include <emscripten/key_codes.h>
|
||||
|
||||
//! Convert Emscripten mouse buttons into Aspect_VKeyMouse.
|
||||
inline Aspect_VKeyMouse WasmVKeys_MouseButtonsFromNative (unsigned short theButtons)
|
||||
{
|
||||
Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
|
||||
if ((theButtons & 0x1) != 0)
|
||||
{
|
||||
aButtons |= Aspect_VKeyMouse_LeftButton;
|
||||
}
|
||||
if ((theButtons & 0x2) != 0)
|
||||
{
|
||||
aButtons |= Aspect_VKeyMouse_RightButton;
|
||||
}
|
||||
if ((theButtons & 0x4) != 0)
|
||||
{
|
||||
aButtons |= Aspect_VKeyMouse_MiddleButton;
|
||||
}
|
||||
return aButtons;
|
||||
}
|
||||
|
||||
//! Convert DOM virtual key into Aspect_VKey.
|
||||
inline Aspect_VKey WasmVKeys_VirtualKeyFromNative (Standard_Integer theKey)
|
||||
{
|
||||
if (theKey >= DOM_VK_0
|
||||
&& theKey <= DOM_VK_9)
|
||||
{
|
||||
// numpad keys
|
||||
return Aspect_VKey((theKey - DOM_VK_0) + Aspect_VKey_0);
|
||||
}
|
||||
if (theKey >= DOM_VK_A
|
||||
&& theKey <= DOM_VK_Z)
|
||||
{
|
||||
// main latin alphabet keys
|
||||
return Aspect_VKey((theKey - DOM_VK_A) + Aspect_VKey_A);
|
||||
}
|
||||
if (theKey >= DOM_VK_F1
|
||||
&& theKey <= DOM_VK_F24)
|
||||
{
|
||||
// special keys
|
||||
if (theKey <= DOM_VK_F12)
|
||||
{
|
||||
return Aspect_VKey((theKey - DOM_VK_F1) + Aspect_VKey_F1);
|
||||
}
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
}
|
||||
if (theKey >= DOM_VK_NUMPAD0
|
||||
&& theKey <= DOM_VK_NUMPAD9)
|
||||
{
|
||||
// numpad keys
|
||||
return Aspect_VKey((theKey - DOM_VK_NUMPAD0) + Aspect_VKey_Numpad0);
|
||||
}
|
||||
|
||||
switch (theKey)
|
||||
{
|
||||
case DOM_VK_CANCEL:
|
||||
case DOM_VK_HELP:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_BACK_SPACE:
|
||||
return Aspect_VKey_Backspace;
|
||||
case DOM_VK_TAB:
|
||||
return Aspect_VKey_Tab;
|
||||
case DOM_VK_CLEAR:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_RETURN:
|
||||
case DOM_VK_ENTER:
|
||||
return Aspect_VKey_Enter;
|
||||
case DOM_VK_SHIFT:
|
||||
return Aspect_VKey_Shift;
|
||||
case DOM_VK_CONTROL:
|
||||
return Aspect_VKey_Control;
|
||||
case DOM_VK_ALT:
|
||||
return Aspect_VKey_Alt;
|
||||
case DOM_VK_PAUSE:
|
||||
case DOM_VK_CAPS_LOCK:
|
||||
case DOM_VK_KANA:
|
||||
//case DOM_VK_HANGUL:
|
||||
case DOM_VK_EISU:
|
||||
case DOM_VK_JUNJA:
|
||||
case DOM_VK_FINAL:
|
||||
case DOM_VK_HANJA:
|
||||
//case DOM_VK_KANJI:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_ESCAPE:
|
||||
return Aspect_VKey_Escape;
|
||||
case DOM_VK_CONVERT:
|
||||
case DOM_VK_NONCONVERT:
|
||||
case DOM_VK_ACCEPT:
|
||||
case DOM_VK_MODECHANGE:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_SPACE:
|
||||
return Aspect_VKey_Space;
|
||||
case DOM_VK_PAGE_UP:
|
||||
return Aspect_VKey_PageUp;
|
||||
case DOM_VK_PAGE_DOWN:
|
||||
return Aspect_VKey_PageDown;
|
||||
case DOM_VK_END:
|
||||
return Aspect_VKey_End;
|
||||
case DOM_VK_HOME:
|
||||
return Aspect_VKey_Home;
|
||||
case DOM_VK_LEFT:
|
||||
return Aspect_VKey_Left;
|
||||
case DOM_VK_UP:
|
||||
return Aspect_VKey_Up;
|
||||
case DOM_VK_RIGHT:
|
||||
return Aspect_VKey_Right;
|
||||
case DOM_VK_DOWN:
|
||||
return Aspect_VKey_Down;
|
||||
case DOM_VK_SELECT:
|
||||
case DOM_VK_PRINT:
|
||||
case DOM_VK_EXECUTE:
|
||||
case DOM_VK_PRINTSCREEN:
|
||||
case DOM_VK_INSERT:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_DELETE:
|
||||
return Aspect_VKey_Delete;
|
||||
case DOM_VK_COLON:
|
||||
return Aspect_VKey_Comma;
|
||||
case DOM_VK_SEMICOLON:
|
||||
return Aspect_VKey_Semicolon;
|
||||
case DOM_VK_LESS_THAN:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_EQUALS:
|
||||
return Aspect_VKey_Equal;
|
||||
case DOM_VK_GREATER_THAN:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_QUESTION_MARK:
|
||||
return Aspect_VKey_Slash;
|
||||
case DOM_VK_AT: // @ key
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_WIN:
|
||||
return Aspect_VKey_Meta;
|
||||
case DOM_VK_CONTEXT_MENU:
|
||||
case DOM_VK_SLEEP:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_MULTIPLY:
|
||||
return Aspect_VKey_NumpadMultiply;
|
||||
case DOM_VK_ADD:
|
||||
return Aspect_VKey_NumpadAdd;
|
||||
case DOM_VK_SEPARATOR:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_SUBTRACT:
|
||||
return Aspect_VKey_NumpadSubtract;
|
||||
case DOM_VK_DECIMAL:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_DIVIDE:
|
||||
return Aspect_VKey_NumpadDivide;
|
||||
case DOM_VK_NUM_LOCK:
|
||||
return Aspect_VKey_Numlock;
|
||||
case DOM_VK_SCROLL_LOCK:
|
||||
return Aspect_VKey_Scroll;
|
||||
case DOM_VK_WIN_OEM_FJ_JISHO:
|
||||
case DOM_VK_WIN_OEM_FJ_MASSHOU:
|
||||
case DOM_VK_WIN_OEM_FJ_TOUROKU:
|
||||
case DOM_VK_WIN_OEM_FJ_LOYA:
|
||||
case DOM_VK_WIN_OEM_FJ_ROYA:
|
||||
case DOM_VK_CIRCUMFLEX:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_EXCLAMATION:
|
||||
case DOM_VK_DOUBLE_QUOTE:
|
||||
//case DOM_VK_HASH:
|
||||
case DOM_VK_DOLLAR:
|
||||
case DOM_VK_PERCENT:
|
||||
case DOM_VK_AMPERSAND:
|
||||
case DOM_VK_UNDERSCORE:
|
||||
case DOM_VK_OPEN_PAREN:
|
||||
case DOM_VK_CLOSE_PAREN:
|
||||
case DOM_VK_ASTERISK:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_PLUS:
|
||||
return Aspect_VKey_Plus;
|
||||
case DOM_VK_PIPE:
|
||||
case DOM_VK_HYPHEN_MINUS:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_OPEN_CURLY_BRACKET:
|
||||
return Aspect_VKey_BracketLeft;
|
||||
case DOM_VK_CLOSE_CURLY_BRACKET:
|
||||
return Aspect_VKey_BracketRight;
|
||||
case DOM_VK_TILDE:
|
||||
return Aspect_VKey_Tilde;
|
||||
case DOM_VK_VOLUME_MUTE:
|
||||
return Aspect_VKey_VolumeMute;
|
||||
case DOM_VK_VOLUME_DOWN:
|
||||
return Aspect_VKey_VolumeDown;
|
||||
case DOM_VK_VOLUME_UP:
|
||||
return Aspect_VKey_VolumeUp;
|
||||
case DOM_VK_COMMA:
|
||||
return Aspect_VKey_Comma;
|
||||
case DOM_VK_PERIOD:
|
||||
return Aspect_VKey_Period;
|
||||
case DOM_VK_SLASH:
|
||||
return Aspect_VKey_Slash;
|
||||
case DOM_VK_BACK_QUOTE:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_OPEN_BRACKET:
|
||||
return Aspect_VKey_BracketLeft;
|
||||
case DOM_VK_BACK_SLASH:
|
||||
return Aspect_VKey_Backslash;
|
||||
case DOM_VK_CLOSE_BRACKET:
|
||||
return Aspect_VKey_BracketRight;
|
||||
case DOM_VK_QUOTE:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_META:
|
||||
return Aspect_VKey_Meta;
|
||||
case DOM_VK_ALTGR:
|
||||
return Aspect_VKey_Alt;
|
||||
case DOM_VK_WIN_ICO_HELP:
|
||||
case DOM_VK_WIN_ICO_00:
|
||||
case DOM_VK_WIN_ICO_CLEAR:
|
||||
case DOM_VK_WIN_OEM_RESET:
|
||||
case DOM_VK_WIN_OEM_JUMP:
|
||||
case DOM_VK_WIN_OEM_PA1:
|
||||
case DOM_VK_WIN_OEM_PA2:
|
||||
case DOM_VK_WIN_OEM_PA3:
|
||||
case DOM_VK_WIN_OEM_WSCTRL:
|
||||
case DOM_VK_WIN_OEM_CUSEL:
|
||||
case DOM_VK_WIN_OEM_ATTN:
|
||||
case DOM_VK_WIN_OEM_FINISH:
|
||||
case DOM_VK_WIN_OEM_COPY:
|
||||
case DOM_VK_WIN_OEM_AUTO:
|
||||
case DOM_VK_WIN_OEM_ENLW:
|
||||
case DOM_VK_WIN_OEM_BACKTAB:
|
||||
case DOM_VK_ATTN:
|
||||
case DOM_VK_CRSEL:
|
||||
case DOM_VK_EXSEL:
|
||||
case DOM_VK_EREOF:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
case DOM_VK_PLAY:
|
||||
return Aspect_VKey_MediaPlayPause;
|
||||
case DOM_VK_ZOOM:
|
||||
case DOM_VK_PA1:
|
||||
case DOM_VK_WIN_OEM_CLEAR:
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
}
|
||||
return Aspect_VKey_UNKNOWN;
|
||||
}
|
||||
|
||||
#endif // _WasmVKeys_HeaderFile
|
Reference in New Issue
Block a user