Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Drag n Drop files in WebGL

Discussion in 'Scripting' started by Cyber-Dog, Apr 2, 2019.

  1. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
  2. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
  3. andrewluck

    andrewluck

    Joined:
    Jun 14, 2016
    Posts:
    1
    +1 - it would great to let user drag n' drop media - sound, video, images, etc...
     
  4. doctorpangloss

    doctorpangloss

    Joined:
    Feb 20, 2013
    Posts:
    267
    It's not really realistic to pipe-in images into the WebGL runtime, due to memory and texture representation issues. A 4k square image will crash your game trying to process it.
     
  5. ainurkamaltdinov

    ainurkamaltdinov

    Joined:
    Dec 28, 2017
    Posts:
    1
    where Unity Web Player app is running?on frontend or backend?
     
  6. webster

    webster

    Joined:
    Jun 8, 2013
    Posts:
    21
  7. julienkay

    julienkay

    Joined:
    Nov 12, 2013
    Posts:
    159
    Thanks, that was a good starting point for me. Unfortunately the custom WebGL Template used in the repository is outdated with newer Unity versions.

    To add Drag & Drop in Unity 2021 follow the docs on how to create custom WebGL Templates: Copy the Default template from C:\Program Files\Unity\Hub\Editor\<version>\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\WebGLTemplates and place it inside the Assets\WebGLTemplates directory in your project.
    Then you'll have to add this code to index.html that sends the drop event to a script in Unity via SendMessage when the Unity game instance is created inside the scripts onload function:
    Code (CSharp):
    1. container.addEventListener('dragover', (event) => {
    2.     event.preventDefault();
    3. });
    4. container.addEventListener('drop', (event) => {
    5.     event.preventDefault();
    6.     const files = event.dataTransfer.files;
    7.     const first = files[0];
    8.     unityInstance.SendMessage("FileReceiver", "FileSelected", window.URL.createObjectURL(first), first);
    9. });
    The complete file looks like this:
    Code (CSharp):
    1. <!DOCTYPE html>
    2. <html lang="en-us">
    3.   <head>
    4.     <meta charset="utf-8">
    5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    6.     <title>Unity WebGL Player | {{{ PRODUCT_NAME }}}</title>
    7.     <link rel="shortcut icon" href="TemplateData/favicon.ico">
    8.     <link rel="stylesheet" href="TemplateData/style.css">
    9.   </head>
    10.   <body>
    11.     <div id="unity-container" class="unity-desktop">
    12.       <canvas id="unity-canvas" width={{{ WIDTH }}} height={{{ HEIGHT }}}></canvas>
    13.       <div id="unity-loading-bar">
    14.         <div id="unity-logo"></div>
    15.         <div id="unity-progress-bar-empty">
    16.           <div id="unity-progress-bar-full"></div>
    17.         </div>
    18.       </div>
    19.       <div id="unity-warning"> </div>
    20.       <div id="unity-footer">
    21.         <div id="unity-webgl-logo"></div>
    22.         <div id="unity-fullscreen-button"></div>
    23.         <div id="unity-build-title">{{{ PRODUCT_NAME }}}</div>
    24.       </div>
    25.     </div>
    26.     <script>
    27.       var container = document.querySelector("#unity-container");
    28.       var canvas = document.querySelector("#unity-canvas");
    29.       var loadingBar = document.querySelector("#unity-loading-bar");
    30.       var progressBarFull = document.querySelector("#unity-progress-bar-full");
    31.       var fullscreenButton = document.querySelector("#unity-fullscreen-button");
    32.       var warningBanner = document.querySelector("#unity-warning");
    33.  
    34.       // Shows a temporary message banner/ribbon for a few seconds, or
    35.       // a permanent error message on top of the canvas if type=='error'.
    36.       // If type=='warning', a yellow highlight color is used.
    37.       // Modify or remove this function to customize the visually presented
    38.       // way that non-critical warnings and error messages are presented to the
    39.       // user.
    40.       function unityShowBanner(msg, type) {
    41.         function updateBannerVisibility() {
    42.           warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
    43.         }
    44.         var div = document.createElement('div');
    45.         div.innerHTML = msg;
    46.         warningBanner.appendChild(div);
    47.         if (type == 'error') div.style = 'background: red; padding: 10px;';
    48.         else {
    49.           if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
    50.           setTimeout(function() {
    51.             warningBanner.removeChild(div);
    52.             updateBannerVisibility();
    53.           }, 5000);
    54.         }
    55.         updateBannerVisibility();
    56.       }
    57.  
    58.       var buildUrl = "Build";
    59.       var loaderUrl = buildUrl + "/{{{ LOADER_FILENAME }}}";
    60.       var config = {
    61.         dataUrl: buildUrl + "/{{{ DATA_FILENAME }}}",
    62.         frameworkUrl: buildUrl + "/{{{ FRAMEWORK_FILENAME }}}",
    63. #if USE_WASM
    64.         codeUrl: buildUrl + "/{{{ CODE_FILENAME }}}",
    65. #endif
    66. #if MEMORY_FILENAME
    67.         memoryUrl: buildUrl + "/{{{ MEMORY_FILENAME }}}",
    68. #endif
    69. #if SYMBOLS_FILENAME
    70.         symbolsUrl: buildUrl + "/{{{ SYMBOLS_FILENAME }}}",
    71. #endif
    72.         streamingAssetsUrl: "StreamingAssets",
    73.         companyName: {{{ JSON.stringify(COMPANY_NAME) }}},
    74.         productName: {{{ JSON.stringify(PRODUCT_NAME) }}},
    75.         productVersion: {{{ JSON.stringify(PRODUCT_VERSION) }}},
    76.         showBanner: unityShowBanner,
    77.       };
    78.  
    79.       // By default Unity keeps WebGL canvas render target size matched with
    80.       // the DOM size of the canvas element (scaled by window.devicePixelRatio)
    81.       // Set this to false if you want to decouple this synchronization from
    82.       // happening inside the engine, and you would instead like to size up
    83.       // the canvas DOM size and WebGL render target sizes yourself.
    84.       // config.matchWebGLToCanvasSize = false;
    85.  
    86.       if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
    87.         // Mobile device style: fill the whole browser client area with the game canvas:
    88.  
    89.         var meta = document.createElement('meta');
    90.         meta.name = 'viewport';
    91.         meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes';
    92.         document.getElementsByTagName('head')[0].appendChild(meta);
    93.         container.className = "unity-mobile";
    94.  
    95.         // To lower canvas resolution on mobile devices to gain some
    96.         // performance, uncomment the following line:
    97.         // config.devicePixelRatio = 1;
    98.  
    99.         canvas.style.width = window.innerWidth + 'px';
    100.         canvas.style.height = window.innerHeight + 'px';
    101.  
    102.         unityShowBanner('WebGL builds are not supported on mobile devices.');
    103.       } else {
    104.         // Desktop style: Render the game canvas in a window that can be maximized to fullscreen:
    105.  
    106.         canvas.style.width = "{{{ WIDTH }}}px";
    107.         canvas.style.height = "{{{ HEIGHT }}}px";
    108.       }
    109.  
    110. #if BACKGROUND_FILENAME
    111.       canvas.style.background = "url('" + buildUrl + "/{{{ BACKGROUND_FILENAME.replace(/'/g, '%27') }}}') center / cover";
    112. #endif
    113.       loadingBar.style.display = "block";
    114.  
    115.       var script = document.createElement("script");
    116.       script.src = loaderUrl;
    117.       script.onload = () => {
    118.         createUnityInstance(canvas, config, (progress) => {
    119.           progressBarFull.style.width = 100 * progress + "%";
    120.         }).then((unityInstance) => {
    121.           loadingBar.style.display = "none";
    122.           fullscreenButton.onclick = () => {
    123.             unityInstance.SetFullscreen(1);
    124.           };
    125.           container.addEventListener('dragover', (event) => {
    126.               event.preventDefault();
    127.           });
    128.           container.addEventListener('drop', (event) => {
    129.               event.preventDefault();
    130.               const files = event.dataTransfer.files;
    131.               const first = files[0];
    132.               unityInstance.SendMessage("FileReceiver", "FileSelected", window.URL.createObjectURL(first), first);
    133.           });
    134.         }).catch((message) => {
    135.           alert(message);
    136.         });
    137.       };
    138.       document.body.appendChild(script);
    139.     </script>
    140.   </body>
    141. </html>
    142.  

    This was the first hit on Google so I thought I'd share.
     
    DoPinG83_CarX and UnderShad like this.