<commit_before>import runtime from '../../core/runtime.js'
import poll from '../../utils/poll.js'
import getFromStorage from '../../storage/get.js'

var validTypes = [
  'interior',
  'group',
  'level',
  'plan',
  'object'
]

export default function toHtml(sceneStructure, options) {
  if (!sceneStructure) {
    console.error('nothing to convert')
    return
  }
  // check if the request was made by a browser
  runtime.assertBrowser()

  // api
  options = options || {}
  var isArray = Array.isArray(sceneStructure)
  sceneStructure = isArray ? sceneStructure : [sceneStructure]

  // start parsing
  var html = getHtmlFromSceneStructure(sceneStructure)
  return isArray ? html : html[0]
}

// recursive parsing through sceneStructre
function getHtmlFromSceneStructure(sceneStructure, parent) {
  var collection = parent ? null : [] // use collection or parent
  sceneStructure.forEach(function(element3d) {
    if (validTypes.indexOf(element3d.type) > -1) {
      var el = addEntity({
        attributes: getAttributes(element3d),
        parent: parent
      })
      if (element3d.type === 'level' && (element3d.bakeRegularStatusFileKey || element3d.bakePreviewStatusFileKey)) {
        updateOnBake(el, element3d)
      }
      if (element3d.children && element3d.children.length) getHtmlFromSceneStructure(element3d.children, el)
      if (collection) collection.push(el)
    }
  })
  return collection
}

// get html attributes from element3d params
function getAttributes(element3d) {
  var attributes = {
    'io3d-uuid': element3d.id,
    position: element3d.x + ' ' + element3d.y + ' ' + element3d.z,
    rotation: '0 ' + element3d.ry + ' 0'
  }

  switch (element3d.type) {
    case 'level':
      if (!element3d.bakedModelUrl) {
        console.warn('Level without bakedModelUrl: ', element3d)
        return
      }
      attributes['io3d-data3d'] = 'key: ' + element3d.bakedModelUrl
      if (element3d.lightMapIntensity) {
        attributes['io3d-data3d'] += '; lightMapIntensity: ' + element3d.lightMapIntensity + '; lightMapExposure: ' + element3d.lightMapCenter
      }
      attributes['shadow'] = 'cast: false, receive: true'
      break
    case 'interior':
      attributes['io3d-furniture'] = 'id: ' + element3d.src.substring(1)
      attributes['shadow'] = 'cast: true, receive: false'
    break
    case 'object':
      attributes['io3d-data3d'] = 'key: ' + element3d.object
      attributes['shadow'] = 'cast: true, receive: true'
    break<commit_msg>Added support for furniture with custom materials<commit_after>import runtime from '../../core/runtime.js'
import poll from '../../utils/poll.js'
import getFromStorage from '../../storage/get.js'

var validTypes = [
  'interior',
  'group',
  'level',
  'plan',
  'object'
]

export default function toHtml(sceneStructure, options) {
  if (!sceneStructure) {
    console.error('nothing to convert')
    return
  }
  // check if the request was made by a browser
  runtime.assertBrowser()

  // api
  options = options || {}
  var isArray = Array.isArray(sceneStructure)
  sceneStructure = isArray ? sceneStructure : [sceneStructure]

  // start parsing
  var html = getHtmlFromSceneStructure(sceneStructure)
  return isArray ? html : html[0]
}

// recursive parsing through sceneStructre
function getHtmlFromSceneStructure(sceneStructure, parent) {
  var collection = parent ? null : [] // use collection or parent
  sceneStructure.forEach(function(element3d) {
    if (validTypes.indexOf(element3d.type) > -1) {
      var el = addEntity({
        attributes: getAttributes(element3d),
        parent: parent
      })
      if (element3d.type === 'level' && (element3d.bakeRegularStatusFileKey || element3d.bakePreviewStatusFileKey)) {
        updateOnBake(el, element3d)
      }
      if (element3d.children && element3d.children.length) getHtmlFromSceneStructure(element3d.children, el)
      if (collection) collection.push(el)
    }
  })
  return collection
}

// get html attributes from element3d params
function getAttributes(element3d) {
  var attributes = {
    'io3d-uuid': element3d.id,
    position: element3d.x + ' ' + element3d.y + ' ' + element3d.z,
    rotation: '0 ' + element3d.ry + ' 0'
  }

  switch (element3d.type) {
    case 'level':
      if (!element3d.bakedModelUrl) {
        console.warn('Level without bakedModelUrl: ', element3d)
        return
      }
      attributes['io3d-data3d'] = 'key: ' + element3d.bakedModelUrl
      if (element3d.lightMapIntensity) {
        attributes['io3d-data3d'] += '; lightMapIntensity: ' + element3d.lightMapIntensity + '; lightMapExposure: ' + element3d.lightMapCenter
      }
      attributes['shadow'] = 'cast: false, receive: true'
      break
    case 'interior':
      attributes['io3d-furniture'] = 'id: ' + element3d.src.substring(1)
      // apply custom material settings for furniture items
      if (element3d.materials) {
        element3d.materials.forEach(function(mat) {
          if (mat.mesh && mat.material) attributes['io3d-furniture'] += '; material_' + mat.mesh.replace(/\s/g, '_') + ':' + mat.material
        })
      }
      attributes['shadow'] = 'cast: true, receive: false'
    break
    case 'object':
      attributes['io3d-data3d'] = 'key: ' + element3d.object
      attributes['shadow'] = 'cast: true, receive: true'
    break
{'fraction_non_alphanumeric': 0.1314996232102487, 'fraction_numerical': 0.015259984928409947, 'mean_word_length': 3.2574178027265437, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6177045', 'n_tokens_mistral': 1662, 'n_tokens_neox': 1645, 'n_words': 364}