mainBuild:
  name: opencascade.ocjsx-viewer.dev-full.js

  emccFlags:
    # These are just the default values as defined in /src/customBuildSchema.py
    # - -O3
    # - -g3
    - -sASSERTIONS=1
    - -sEXPORT_ES6=1
    - -sUSE_ES6_IMPORT_META=1
    - -sEXPORTED_RUNTIME_METHODS=['FS']
    - -sINITIAL_MEMORY=100MB
    - -sMAXIMUM_MEMORY=4GB
    - -sALLOW_MEMORY_GROWTH=1
    - -sUSE_FREETYPE=1
    - -sLLD_REPORT_UNDEFINED
    - --no-entry
    - |
      -sPTHREAD_POOL_SIZE='globalThis.ocThreadCount ?? (navigator.hardwareConcurrency ?? 6)'
    - -sENVIRONMENT='web,worker'
    - -sDISABLE_EXCEPTION_CATCHING=0
    # - -flto
    - -sMAX_WEBGL_VERSION=2
    - -sWEBGL2_BACKWARDS_COMPATIBILITY_EMULATION=1
    - /src/freeimage/Dist/libfreeimage.a

additionalCppCode: |
  #include <string>
  #include <iostream>
  #include <emscripten/html5.h>
  #include <emscripten/val.h>
  typedef Handle(IMeshTools_Context) Handle_IMeshTools_Context;

  class OCJS {
  public:
    static Standard_Failure* getStandard_FailureData(intptr_t exceptionPtr) {
      return reinterpret_cast<Standard_Failure*>(exceptionPtr);
    }
  };

  class Test {
  public:
    static void SetWindow(V3d_View* v, const Handle(Aspect_Window)& w) {
      v->SetWindow(w);
      // v->ChangeRenderingParams().IsAntialiasingEnabled = true;
      // v->ChangeRenderingParams().Resolution = (unsigned int )(96.0 * myDevicePixelRatio + 0.5);
    }
    static AIS_InteractiveContext* castAIS_InteractiveContext(intptr_t ptr) {
      return reinterpret_cast<AIS_InteractiveContext*>(ptr);
    }
    static V3d_View* castV3d_View(intptr_t ptr) {
      return reinterpret_cast<V3d_View*>(ptr);
    }
    static AIS_ViewController* castAIS_ViewController(intptr_t ptr) {
      return reinterpret_cast<AIS_ViewController*>(ptr);
    }
    static Handle_AIS_InteractiveObject* castHandle_AIS_InteractiveObject(intptr_t ptr) {
      return reinterpret_cast<Handle_AIS_InteractiveObject*>(ptr);
    }
    static Graphic3d_ClipPlane* castGraphic3d_ClipPlane(intptr_t ptr) {
      return reinterpret_cast<Graphic3d_ClipPlane*>(ptr);
    }
    static bool ProcessWheelEvent(Wasm_Window* w, Aspect_WindowInputListener& theListener, emscripten::val event) {
      EmscriptenWheelEvent theEvent;
      theEvent.mouse.timestamp = event["timestamp"].as<double>();
      theEvent.mouse.screenX = event["screenX"].as<long>();
      theEvent.mouse.screenY = event["screenY"].as<long>();
      theEvent.mouse.clientX = event["clientX"].as<long>();
      theEvent.mouse.clientY = event["clientY"].as<long>();
      theEvent.mouse.ctrlKey = event["ctrlKey"].as<EM_BOOL>();
      theEvent.mouse.shiftKey = event["shiftKey"].as<EM_BOOL>();
      theEvent.mouse.altKey = event["altKey"].as<EM_BOOL>();
      theEvent.mouse.metaKey = event["metaKey"].as<EM_BOOL>();
      theEvent.mouse.button = event["button"].as<short>();
      theEvent.mouse.buttons = event["buttons"].as<short>();
      theEvent.mouse.movementX = event["movementX"].as<long>();
      theEvent.mouse.movementY = event["movementY"].as<long>();
      theEvent.mouse.targetX = event["targetX"].as<long>();
      theEvent.mouse.targetY = event["targetY"].as<long>();
      theEvent.deltaX = event["deltaX"].as<double>();
      theEvent.deltaY = event["deltaY"].as<double>();
      theEvent.deltaZ = event["deltaZ"].as<double>();
      theEvent.deltaMode = event["deltaMode"].as<unsigned long>();
      return w->ProcessWheelEvent(theListener, EMSCRIPTEN_EVENT_WHEEL, &theEvent);
    }
    static bool ProcessMouseEvent(Wasm_Window* w, Aspect_WindowInputListener& theListener, emscripten::val event, int eventType) {
      EmscriptenMouseEvent theEvent;
      theEvent.timestamp = event["timestamp"].as<double>();
      theEvent.screenX = event["screenX"].as<long>();
      theEvent.screenY = event["screenY"].as<long>();
      theEvent.clientX = event["clientX"].as<long>();
      theEvent.clientY = event["clientY"].as<long>();
      theEvent.ctrlKey = event["ctrlKey"].as<EM_BOOL>();
      theEvent.shiftKey = event["shiftKey"].as<EM_BOOL>();
      theEvent.altKey = event["altKey"].as<EM_BOOL>();
      theEvent.metaKey = event["metaKey"].as<EM_BOOL>();
      theEvent.button = event["button"].as<short>();
      theEvent.buttons = event["buttons"].as<short>();
      theEvent.movementX = event["movementX"].as<long>();
      theEvent.movementY = event["movementY"].as<long>();
      theEvent.targetX = event["targetX"].as<long>();
      theEvent.targetY = event["targetY"].as<long>();
      return w->ProcessMouseEvent(theListener, eventType, &theEvent);
    }
    static bool ProcessTouchEvent(Wasm_Window* w, Aspect_WindowInputListener& theListener, emscripten::val event, int eventType) {
      EmscriptenTouchEvent theEvent;
      theEvent.timestamp = event["timestamp"].as<double>();
      theEvent.numTouches = event["numTouches"].as<int>();
      theEvent.ctrlKey = event["ctrlKey"].as<EM_BOOL>();
      theEvent.shiftKey = event["shiftKey"].as<EM_BOOL>();
      theEvent.altKey = event["altKey"].as<EM_BOOL>();
      theEvent.metaKey = event["metaKey"].as<EM_BOOL>();

      if(theEvent.numTouches >= 1) {
        theEvent.touches[0].identifier = event["touches0"]["identifier"].as<long>();
        theEvent.touches[0].screenX = event["touches0"]["screenX"].as<long>();
        theEvent.touches[0].screenY = event["touches0"]["screenY"].as<long>();
        theEvent.touches[0].clientX = event["touches0"]["clientX"].as<long>();
        theEvent.touches[0].clientY = event["touches0"]["clientY"].as<long>();
        theEvent.touches[0].pageX = event["touches0"]["pageX"].as<long>();
        theEvent.touches[0].pageY = event["touches0"]["pageY"].as<long>();
        theEvent.touches[0].isChanged = event["touches0"]["isChanged"].as<EM_BOOL>();
        theEvent.touches[0].onTarget = event["touches0"]["onTarget"].as<EM_BOOL>();
        theEvent.touches[0].targetX = event["touches0"]["targetX"].as<long>();
        theEvent.touches[0].targetY = event["touches0"]["targetY"].as<long>();
      }

      if(theEvent.numTouches >= 2) {
        theEvent.touches[1].identifier = event["touches1"]["identifier"].as<long>();
        theEvent.touches[1].screenX = event["touches1"]["screenX"].as<long>();
        theEvent.touches[1].screenY = event["touches1"]["screenY"].as<long>();
        theEvent.touches[1].clientX = event["touches1"]["clientX"].as<long>();
        theEvent.touches[1].clientY = event["touches1"]["clientY"].as<long>();
        theEvent.touches[1].pageX = event["touches1"]["pageX"].as<long>();
        theEvent.touches[1].pageY = event["touches1"]["pageY"].as<long>();
        theEvent.touches[1].isChanged = event["touches1"]["isChanged"].as<EM_BOOL>();
        theEvent.touches[1].onTarget = event["touches1"]["onTarget"].as<EM_BOOL>();
        theEvent.touches[1].targetX = event["touches1"]["targetX"].as<long>();
        theEvent.touches[1].targetY = event["touches1"]["targetY"].as<long>();
      }

      return w->ProcessTouchEvent(theListener, eventType, &theEvent);
    }
    static emscripten::val GetListOfGDTShapes(XCAFDoc_DimTolTool* dimTolTool) {
      NCollection_IndexedDataMap<TDF_Label, TopoDS_Shape, TDF_LabelMapHasher> theGDTLabelToShape;
      dimTolTool->GetGDTPresentations(theGDTLabelToShape);
      emscripten::val ret = emscripten::val::array();
      int ii = 0;
      for(auto i = theGDTLabelToShape.begin(); i != theGDTLabelToShape.end(); i++) {
        ret.set(ii++, emscripten::val(*i));
      }
      return ret;
    }
  };
