2
0
Эх сурвалжийг харах

webgl: Improve canvas resizing behavior

Automatically resize canvas to the CSS size
rdb 9 сар өмнө
parent
commit
7c16720bb9

+ 72 - 4
panda/src/webgldisplay/webGLGraphicsWindow.cxx

@@ -20,6 +20,13 @@
 #include "pointerData.h"
 #include "pointerData.h"
 #include <emscripten.h>
 #include <emscripten.h>
 
 
+#ifndef CPPPARSER
+extern "C" void EMSCRIPTEN_KEEPALIVE
+_canvas_resized(WebGLGraphicsWindow *window, double width, double height) {
+  window->on_resize(width, height);
+}
+#endif
+
 TypeHandle WebGLGraphicsWindow::_type_handle;
 TypeHandle WebGLGraphicsWindow::_type_handle;
 
 
 /**
 /**
@@ -171,8 +178,9 @@ set_properties_now(WindowProperties &properties) {
   const char *target = "#canvas";
   const char *target = "#canvas";
 
 
   if (properties.has_size()) {
   if (properties.has_size()) {
-    emscripten_set_canvas_element_size(target, properties.get_x_size(), properties.get_y_size());
     _properties.set_size(properties.get_size());
     _properties.set_size(properties.get_size());
+    emscripten_set_canvas_element_size(target, properties.get_x_size(), properties.get_y_size());
+    emscripten_set_element_css_size(target, properties.get_x_size(), properties.get_y_size());
     properties.clear_size();
     properties.clear_size();
     set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size());
     set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size());
     throw_event(get_window_event(), this);
     throw_event(get_window_event(), this);
@@ -260,6 +268,14 @@ close_window() {
     _gsg.clear();
     _gsg.clear();
   }
   }
 
 
+  EM_ASM({
+    var canvas = document.getElementById('canvas');
+    if (canvas && canvas._p3d_resizeObserver) {
+      canvas._p3d_resizeObserver.disconnect();
+      delete canvas._p3d_resizeObserver;
+    }
+  });
+
   // Clear the assigned callbacks.
   // Clear the assigned callbacks.
   const char *target = "#canvas";
   const char *target = "#canvas";
   emscripten_set_fullscreenchange_callback(target, nullptr, false, nullptr);
   emscripten_set_fullscreenchange_callback(target, nullptr, false, nullptr);
@@ -317,11 +333,22 @@ open_window() {
     return false;
     return false;
   }
   }
 
 
-  if (_properties.has_size() && _properties.get_size() != LVecBase2i(1, 1)) {
+  // For now, always use the size specified in the CSS, except when fixed size
+  // has been specified, or the CSS has no size
+  double css_width, css_height;
+  emscripten_get_element_css_size(target, &css_width, &css_height);
+
+  if (_properties.has_size() && (_properties.get_fixed_size() || css_width == 0.0 || css_height == 0.0)) {
     emscripten_set_canvas_element_size(target, _properties.get_x_size(), _properties.get_y_size());
     emscripten_set_canvas_element_size(target, _properties.get_x_size(), _properties.get_y_size());
+    emscripten_set_element_css_size(target, _properties.get_x_size(), _properties.get_y_size());
   } else {
   } else {
-    int width, height;
-    emscripten_get_canvas_element_size(target, &width, &height);
+    int width = (int)css_width;
+    int height = (int)css_height;
+    if (width == 0 || height == 0) {
+      emscripten_get_canvas_element_size(target, &width, &height);
+    } else {
+      emscripten_set_canvas_element_size(target, width, height);
+    }
     _properties.set_size(width, height);
     _properties.set_size(width, height);
 
 
     EmscriptenFullscreenChangeEvent event;
     EmscriptenFullscreenChangeEvent event;
@@ -379,6 +406,29 @@ open_window() {
 
 
   emscripten_set_wheel_callback(target, user_data, false, &on_wheel_event);
   emscripten_set_wheel_callback(target, user_data, false, &on_wheel_event);
 
 
+  // Emscripten has no working resize handler for the canvas element, we'll
+  // have to create our own
+  EM_ASM({
+    var canvas = document.getElementById('canvas');
+    if (canvas) {
+      var observer = new ResizeObserver(function(entries) {
+        var entry = entries[0];
+        if (entry) {
+          var width = entry.contentRect.width;
+          var height = entry.contentRect.height;
+          if (width != 0 && height != 0) {
+            __canvas_resized($0, entry.contentRect.width, entry.contentRect.height);
+          }
+        }
+      });
+      observer.observe(canvas);
+      if (canvas._p3d_resizeObserver) {
+        canvas._p3d_resizeObserver.disconnect();
+      }
+      canvas._p3d_resizeObserver = observer;
+    }
+  }, this);
+
   if (!_properties.has_foreground() || _properties.get_foreground()) {
   if (!_properties.has_foreground() || _properties.get_foreground()) {
     _properties.set_foreground(EM_ASM_INT({
     _properties.set_foreground(EM_ASM_INT({
       var canvas = document.getElementById('canvas');
       var canvas = document.getElementById('canvas');
@@ -395,6 +445,24 @@ open_window() {
   return true;
   return true;
 }
 }
 
 
+/**
+ *
+ */
+void WebGLGraphicsWindow::
+on_resize(double width, double height) {
+  if (_properties.get_fixed_size()) {
+    return;
+  }
+
+  const char *target = "#canvas";
+
+  LVecBase2i size((int)width, (int)height);
+  emscripten_set_canvas_element_size(target, size[0], size[1]);
+  if (_properties.get_size() != size) {
+    system_changed_properties(WindowProperties::size(size));
+  }
+}
+
 /**
 /**
  *
  *
  */
  */

+ 3 - 0
panda/src/webgldisplay/webGLGraphicsWindow.h

@@ -48,6 +48,9 @@ protected:
   virtual void close_window();
   virtual void close_window();
   virtual bool open_window();
   virtual bool open_window();
 
 
+public:
+  void on_resize(double width, double height);
+
 private:
 private:
   static EM_BOOL on_fullscreen_event(int type, const EmscriptenFullscreenChangeEvent *event, void *user_data);
   static EM_BOOL on_fullscreen_event(int type, const EmscriptenFullscreenChangeEvent *event, void *user_data);
   static EM_BOOL on_pointerlock_event(int type, const EmscriptenPointerlockChangeEvent *event, void *user_data);
   static EM_BOOL on_pointerlock_event(int type, const EmscriptenPointerlockChangeEvent *event, void *user_data);