Showing preview only (1,183K chars total). Download the full file or copy to clipboard to get everything.
Repository: MozillaReality/hubs-blender-exporter
Branch: master
Commit: d46b4db6d99d
Files: 215
Total size: 1.1 MB
Directory structure:
gitextract_dnqs3d2a/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report-blender-add-on.md
│ │ └── feature_request.md
│ └── workflows/
│ ├── publish.yml
│ └── roadmap-auto-commenter.yml
├── .gitignore
├── .vscode/
│ ├── launch.json
│ └── settings.json
├── LICENSE
├── Pipfile
├── README.md
├── addons/
│ └── io_hubs_addon/
│ ├── .pylintrc
│ ├── __init__.py
│ ├── api.py
│ ├── components/
│ │ ├── __init__.py
│ │ ├── components_registry.py
│ │ ├── consts.py
│ │ ├── definitions/
│ │ │ ├── ambient_light.py
│ │ │ ├── ammo_shape.py
│ │ │ ├── audio.py
│ │ │ ├── audio_params.py
│ │ │ ├── audio_settings.py
│ │ │ ├── audio_source.py
│ │ │ ├── audio_target.py
│ │ │ ├── audio_zone.py
│ │ │ ├── billboard.py
│ │ │ ├── directional_light.py
│ │ │ ├── environment_settings.py
│ │ │ ├── fog.py
│ │ │ ├── frustrum.py
│ │ │ ├── hemisphere_light.py
│ │ │ ├── image.py
│ │ │ ├── link.py
│ │ │ ├── loop_animation.py
│ │ │ ├── media_frame.py
│ │ │ ├── mirror.py
│ │ │ ├── model.py
│ │ │ ├── morph_audio_feedback.py
│ │ │ ├── nav_mesh.py
│ │ │ ├── networked.py
│ │ │ ├── particle_emitter.py
│ │ │ ├── pdf.py
│ │ │ ├── personal_space_invader.py
│ │ │ ├── point_light.py
│ │ │ ├── reflection_probe.py
│ │ │ ├── scale_audio_feedback.py
│ │ │ ├── scene_preview_camera.py
│ │ │ ├── shadow.py
│ │ │ ├── simple_water.py
│ │ │ ├── skybox.py
│ │ │ ├── spawner.py
│ │ │ ├── spoke/
│ │ │ │ ├── background.py
│ │ │ │ ├── box_collider.py
│ │ │ │ └── spawn_point.py
│ │ │ ├── spot_light.py
│ │ │ ├── text.py
│ │ │ ├── uv_scroll.py
│ │ │ ├── video.py
│ │ │ ├── video_texture_source.py
│ │ │ ├── video_texture_target.py
│ │ │ ├── visible.py
│ │ │ └── waypoint.py
│ │ ├── gizmos.py
│ │ ├── handlers.py
│ │ ├── hubs_component.py
│ │ ├── models/
│ │ │ ├── audio.py
│ │ │ ├── box.py
│ │ │ ├── directional_light.py
│ │ │ ├── image.py
│ │ │ ├── link.py
│ │ │ ├── particle_emitter.py
│ │ │ ├── point_light.py
│ │ │ ├── scene_preview_camera.py
│ │ │ ├── spawn_point.py
│ │ │ ├── spot_light.py
│ │ │ └── video.py
│ │ ├── operators.py
│ │ ├── types.py
│ │ ├── ui.py
│ │ └── utils.py
│ ├── debugger.py
│ ├── dependencies/
│ │ └── __init__.py
│ ├── hubs_session.py
│ ├── icons.py
│ ├── io/
│ │ ├── gltf_exporter.py
│ │ ├── gltf_importer.py
│ │ ├── panels.py
│ │ └── utils.py
│ ├── nodes/
│ │ ├── __init__.py
│ │ └── lightmap.py
│ ├── preferences.py
│ ├── third_party/
│ │ ├── __init__.py
│ │ └── recast.py
│ └── utils.py
├── check_style.py
├── format.py
├── gizmos/
│ ├── audio.blend
│ ├── box.blend
│ ├── directional_light.blend
│ ├── image.blend
│ ├── link.blend
│ ├── particle_emitter.blend
│ ├── point_light.blend
│ ├── scene_preview_camera.blend
│ ├── spawn_point.blend
│ ├── spot_light.blend
│ └── video.blend
├── scripts/
│ └── export_gizmo.py
├── setup.sh
├── tests/
│ ├── .eslintrc.json
│ ├── .npmrc
│ ├── export_gltf.py
│ ├── package.json
│ ├── roundtrip_gltf.py
│ ├── scenes/
│ │ ├── ambient-light.blend
│ │ ├── ammo-shape.blend
│ │ ├── audio-settings.blend
│ │ ├── audio-target.blend
│ │ ├── audio-zone.blend
│ │ ├── audio.blend
│ │ ├── billboard.blend
│ │ ├── directional-light.blend
│ │ ├── environment-settings.blend
│ │ ├── fog.blend
│ │ ├── frustrum.blend
│ │ ├── hemisphere-light.blend
│ │ ├── image.blend
│ │ ├── lightmap.blend
│ │ ├── link.blend
│ │ ├── loop-animation.blend
│ │ ├── media-frame.blend
│ │ ├── model.blend
│ │ ├── morph-audio-feedback.blend
│ │ ├── nav-mesh.blend
│ │ ├── particle-emitter.blend
│ │ ├── pdf.blend
│ │ ├── personal-space-invader.blend
│ │ ├── point-light.blend
│ │ ├── reflection-probe.blend
│ │ ├── scale-audio-feedback.blend
│ │ ├── shadow.blend
│ │ ├── simple-water.blend
│ │ ├── skybox.blend
│ │ ├── spawner.blend
│ │ ├── spot-light.blend
│ │ ├── text.blend
│ │ ├── text_clip-rect.blend
│ │ ├── uv-scroll.blend
│ │ ├── video-texture.blend
│ │ ├── video.blend
│ │ ├── visible.blend
│ │ └── waypoint.blend
│ └── test/
│ ├── test_export.js
│ ├── tests/
│ │ ├── ambient-light.js
│ │ ├── ammo-shape.js
│ │ ├── audio-settings.js
│ │ ├── audio-target.js
│ │ ├── audio-zone.js
│ │ ├── audio.js
│ │ ├── billboard.js
│ │ ├── directional-light.js
│ │ ├── environment-settings.js
│ │ ├── fog.js
│ │ ├── frustrum.js
│ │ ├── hemisphere-light.js
│ │ ├── image.js
│ │ ├── link.js
│ │ ├── loop-animation.js
│ │ ├── media-frame.js
│ │ ├── model.js
│ │ ├── morph-audio-feedback.js
│ │ ├── nav-mesh.js
│ │ ├── particle-emitter.js
│ │ ├── personal-space-invader.js
│ │ ├── point-light.js
│ │ ├── scale-audio-feedback.js
│ │ ├── shadow.js
│ │ ├── simple-water.js
│ │ ├── skybox.js
│ │ ├── spawner.js
│ │ ├── spot-light.js
│ │ ├── text.js
│ │ ├── text_clip-rect.js
│ │ ├── uv-scroll.js
│ │ ├── video-texture.js
│ │ ├── video.js
│ │ ├── visible.js
│ │ └── waypoint.js
│ └── utils.js
└── third_parties/
└── recast/
├── app/
│ ├── CMakeLists.txt
│ ├── main.cpp
│ ├── mesh_navmesh.cpp
│ ├── mesh_navmesh.h
│ ├── recast-capi.cpp
│ ├── recast-capi.h
│ └── recast-capi_global.h
└── recast/
├── CMakeLists.txt
├── CONTRIBUTING.md
├── License.txt
├── README.md
├── Recast/
│ ├── CMakeLists.txt
│ ├── Include/
│ │ ├── Recast.h
│ │ ├── RecastAlloc.h
│ │ └── RecastAssert.h
│ └── Source/
│ ├── Recast.cpp
│ ├── RecastAlloc.cpp
│ ├── RecastArea.cpp
│ ├── RecastAssert.cpp
│ ├── RecastContour.cpp
│ ├── RecastFilter.cpp
│ ├── RecastLayers.cpp
│ ├── RecastMesh.cpp
│ ├── RecastMeshDetail.cpp
│ ├── RecastRasterization.cpp
│ └── RecastRegion.cpp
└── readme-addon.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report-blender-add-on.md
================================================
---
name: Bug Report Blender Add-On
about: Help improve the Hubs Blender add-on with quality bug-reports
title: ''
labels: ''
assignees: ''
---
**Description**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
*Please include detailed steps so others can reproduce*
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Hardware** <!-- Please complete the following information -->
- Add-on Release Version:
- Blender Version:
**Additional context**
*Scene Links, models, any other helpful context*
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish
on:
push:
branches:
- master
paths-ignore: ["README.md", "LICENSE", ".gitignore", ".idea", ".vscode", ".github/ISSUE_TEMPLATE"]
pull_request:
workflow_dispatch:
permissions: {}
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Python Linter
uses: weibullguy/python-lint-plus@c1913ebcf442cb2901a919858b0146fef4f007fa # v1.12.0
with:
python-root-list: "addons"
use-black: false
use-yapf: false
use-isort: false
use-docformatter: false
use-pycodestyle: true
use-autopep8: false
use-pydocstyle: false
use-mypy: false
use-pylint: false
use-flake8: false
use-mccabe: false
use-radon: false
use-rstcheck: false
use-check-manifest: false
use-pyroma: false
extra-black-options: ""
extra-yapf-options: ""
extra-isort-options: ""
extra-docformatter-options: ""
# This should work with **/models but it doesn't
extra-pycodestyle-options: "--exclude=models --ignore=E501,W504"
extra-pydocstyle-options: ""
extra-mypy-options: ""
extra-pylint-options: ""
extra-flake8-options: ""
extra-mccabe-options: ""
extra-radon-options: ""
extra-rstcheck-options: ""
extra-manifest-options: ""
extra-pyroma-options: ""
test:
needs: lint
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
version: ["3.6.23", "4.0.2", "4.1.1", "4.2.19", "4.3.2", "4.4.3", "4.5.8", "5.0.1", "5.1.1" ]
timeout-minutes: 20
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# Finds latest Blender build, and outputs the hosted build's download URL.
- name: Find latest Blender build
id: blender_version
run: |
echo ${{ matrix.version }}
major=$(echo ${{ matrix.version }} | cut -d. -f1)
minor=$(echo ${{ matrix.version }} | cut -d. -f2)
patch=$(echo ${{ matrix.version }} | cut -d. -f3)
echo "Looking for Blender $BLENDER_MAJOR.$BLENDER_MINOR.${BLENDER_PATCH}"
BLENDER_URL="https://download.blender.org/release/Blender$major.$minor/blender-$major.$minor.$patch-linux-x64.tar.xz"
echo "blender-url=$BLENDER_URL" >> $GITHUB_OUTPUT
# Loads a cached build of Blender if available. If not available, this step
# enqueues the /opt/blender directory to be cached after tests pass.
- id: blender_cache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
env:
cache-name: cache-blender
with:
path: /opt/blender
key: ${{ steps.blender_version.outputs.blender-url }}
# Downloads a build from blender.org, if a cached version was not available.
- name: Download Blender
if: ${{ !steps.blender_cache.outputs.cache-hit }}
run: |
mkdir /opt/blender
echo "Downloading: ${STEPS_BLENDER_VERSION_OUTPUTS_BLENDER_URL}"
curl -SL "${STEPS_BLENDER_VERSION_OUTPUTS_BLENDER_URL}" | \
tar -Jx -C /opt/blender --strip-components=1
env:
STEPS_BLENDER_VERSION_OUTPUTS_BLENDER_URL: ${{ steps.blender_version.outputs.blender-url }}
- name: Set up workspace
run: |
sudo ln -s /opt/blender/blender /usr/local/bin/blender
blender --version
major=$(echo ${{ matrix.version }} | cut -d. -f1)
minor=$(echo ${{ matrix.version }} | cut -d. -f2)
ADDON_DIR=/opt/blender/$major.$minor/scripts/addons
rm -rf $ADDON_DIR/io_hubs_addon
cp -r addons/io_hubs_addon $ADDON_DIR
cd tests
yarn install
mkdir -p out
- name: Run tests
run: |
cd tests
OUT_PREFIX=$GITHUB_WORKSPACE/tests/out yarn test-bail --reporter-options reportDir=out/mochawesome
- name: Upload test artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: test-output-${{ matrix.version }}
path: tests/out/mochawesome
if-no-files-found: error
publish:
needs: test
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Update build number
run: |
sed -i'' 's/"dev_build"/${{ github.run_number }}/g' $GITHUB_WORKSPACE/addons/io_hubs_addon/__init__.py
- name: Get version
id: get_version
run: |
VERSION=$(grep '"version"' $GITHUB_WORKSPACE/addons/io_hubs_addon/__init__.py | sed -E 's/.*\(([0-9]+), ([0-9]+), ([0-9]+), ([0-9]+)\).*/\1.\2.\3.\4/')
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Upload addon artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: io_hubs_addon_${{ steps.get_version.outputs.version }}
path: addons
if-no-files-found: error
include-hidden-files: true
================================================
FILE: .github/workflows/roadmap-auto-commenter.yml
================================================
# When modifying this file, make sure to pass on the update to all repositories. A tool like https://github.com/gruntwork-io/git-xargs may be useful for this.
# WARNING: This workflow is sometimes triggered by pull_request_target and so will always run automatically on pull requests made by anyone. Do not do any sort of processing of user input, such as checking out code.
name: Roadmap Auto Commenter
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
jobs:
call_reusable_roadmap_auto_commenter:
permissions:
issues: write
pull-requests: write
uses: Hubs-Foundation/.github/.github/workflows/reusable-roadmap-auto-commenter.yml@main
================================================
FILE: .gitignore
================================================
fake_bpy_modules*
__pycache__
.DS_Store
io_scene_gltf2
# Tests
node_modules/
mochawesome-report
tests_out/
generated_cubemaps/
# CMake
CMakeFiles
cmake_install.cmake
CMakeCache.txt
Makefile
lib
# Selenium
__hubs_selenium_profile
# Dependencies
addons/io_hubs_addon/.__deps__
================================================
FILE: .vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Tests",
"request": "launch",
"runtimeArgs": [
"run-script",
"test"
],
"runtimeExecutable": "npm",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node",
"cwd": "${workspaceFolder}/tests"
},
{
"name": "Python: Remote Attach",
"type": "python",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}"
}
],
"justMyCode": true
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"python.autoComplete.extraPaths": [
"./fake_bpy_modules_3.3-20221006"
],
"python.formatting.provider": "autopep8",
"python.formatting.autopep8Args": [
"--exclude=models", "--max-line-length", "120", "--experimental"
],
"python.analysis.extraPaths": [
"./fake_bpy_modules_3.3-20221006"
],
"editor.defaultFormatter": "ms-python.autopep8",
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"autopep8.args": [
"--exclude=models", "--max-line-length", "120", "--experimental"
],
}
================================================
FILE: LICENSE
================================================
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
================================================
FILE: Pipfile
================================================
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
fake-bpy-module-2-82 = "*"
[packages]
[requires]
python_version = "3.8"
================================================
FILE: README.md
================================================
# Hubs Blender Exporter and Importer
This addon extends the glTF 2.0 exporter to support the `MOZ_hubs_components` and `MOZ_lightmap` extensions allowing you to add behavior to glTF assets for Hubs.
[](https://github.com/Hubs-Foundation/hubs-blender-exporter/actions/workflows/test.yml)
[](https://github.com/Hubs-Foundation/hubs-blender-exporter/actions/workflows/publish.yml)
# To Install
Find the latest [release](https://github.com/Hubs-Foundation/hubs-blender-exporter/releases) and download the add-on zip file.
<img alt="select add-on zip file" src="https://user-images.githubusercontent.com/837184/204576860-316b32de-8654-48a7-b9a7-3c0de1c1b652.png" width=685px height=330px />
In Blender: `Edit > Preferences > Add-ons`
Click install and select the zip file of the latest release.
<img width="780" alt="in blender prefs install addon" src="https://user-images.githubusercontent.com/4493657/102955927-dcc56900-448b-11eb-8bfa-07e68b31cffd.png">
Ensure the Hubs add-on is checked and enabled.
<img width="494" alt="hubs blender add-on installed" src="https://user-images.githubusercontent.com/4493657/102956859-c9b39880-448d-11eb-9f02-2f529f14c139.png">
# Adding Components
To add components, go to the "Hubs" section of the properties panel for the thing you want to add a component to. Currently adding components is supported on Scenes, Objects, Bones, and Materials.
<img src="https://user-images.githubusercontent.com/130735/84547528-97440a00-acb8-11ea-9f07-24c919796a3c.png" width="300px"/>
Click "Add Component" and select the component you wish to add from the list. Only components appropriate for the object type you are currently editing and have not already been added will be shown.
# Using Lightmaps
To use a lightmap, create a `MOZ_lightmap` node from the `Add > Hubs` menu and hook up a image texture to the `Lightmap` input. Use a `UV Map` node to control what UV set should be used for the lightmap, as you would any other texture in Blender.

Note that for use in Hubs, you currently **MUST** use the second UV set, as ThreeJS is currently hardcoded to use that for lightmaps. This will likely be fixed in the future so the add-on does not enforce this.

# Exporting
This addon works in conjunction with the official glTF add-on, so exporting is done through it. Select "File > Export > glTF 2.0" and then ensure "Hubs Components" is enabled under "Extensions".

# Import into Hubs
The easiest way to use your scene file is through the Spoke project creation page and selecting _Import From Blender_:
<img width="710" alt="Screenshot 2021-10-31 at 14 05 21" src="https://user-images.githubusercontent.com/303516/139588457-8d9d7835-6101-4cfc-886b-ad3e86c37846.png">
This will bring up the Publish Scene From Blender dialog where you can upload your GLB file and a thumbnail picture for your scene:
<img width="826" alt="Screenshot 2021-10-31 at 14 31 44" src="https://user-images.githubusercontent.com/303516/139588871-ca440552-a270-4feb-9208-65b65ee02b4a.png">
It is also possible to use the GLB file to replace the scene for an existing Hubs room directly by going to Room Settings > Change Scene > Custom Scene and entering the URL of the GLB file. This assumes the file has been already uploaded to an online storage provider.
# Scene debugger
The Hubs Blender add-on includes a scene debugger, enabling you to see the Blender scene updates in Hubs with just one click. For additional information, please visit: https://github.com/Hubs-Foundation/hubs-blender-exporter/wiki/Hubs-scene-debugger/
# Development
## Code Completion
To enable code completion for the Blender Python API you can install the [Fake Blender Python API module collection](https://github.com/nutti/fake-bpy-module/). You can download the modules using the `setup.sh` script from the repository root or using [pip](https://github.com/nutti/fake-bpy-module/#install-via-pip-package).
## Code style
This repository follows the [PEP8](https://peps.python.org/pep-0008/) style convention for python files. If you use VSCode this repository already includes a setting to autoformat every python file when saved. If you don't use VSCode you can probably add a similar setting in your favorite editor. We are happy to add settings for other editors so feel free to open a PR if you want your editor's settings included.
We also include a `format.py` python script that will format the whole codebase when run. You can run it before pushing the PR to make sure that all the new code follows PEP8.
Both the python script and the VSCode settings rely on the [autopep8](https://pypi.org/project/autopep8/) command line tool for formatting so make sure that it's installed in your system.
## Addon development
It might be useful while developing to be able to load the addon directly from the checkout folder without needing to install it. You can do it in two ways:
- ### Overriding the Blender user scripts directory
You can override the Blender user scripts directory from the console to point to the addon repo directory.
**MacOS**
`BLENDER_USER_SCRIPTS=full_path_to_/hubs-blender-exporter /Applications/Blender.app/Contents/MacOS/Blender`
**Linux**
`BLENDER_USER_SCRIPTS=full_path_to_/hubs-blender-exporter blender`
- ### Symlinking your addon to the Blender user scripts directory
You can create a symbolic link pointing to `full_path_to_/hubs-blender-exporter/addons/io_hubs_addon` in your current Python scripts directory in Blender. This way you will also load any other addons that you have in that directory.
**MacOS and Linux**
`ln -s full_path_to/hubs-blender-exporter/addons/io_hubs_addon full_path_to/blender_user_scripts_dir`
You can set or see the current Blender user scripts in the Preferences -> File Paths -> Scripts
## Component export hooks
When adding or modifying Hubs components, the exporter lifecycle uses a few different hooks with different responsibilities (these are defined in hubs_component.py and optionally overridden in specific components):
- `pre_export`
- Runs before export starts.
- Best used for export setup or preprocessing that must happen before gathering data.
- Avoid using this for component data validation that is tied to exported output.
- `gather`
- Runs when component data is exported.
- Best place for component-specific export logic and export-time validation related to exported data.
- `post_export`
- Runs after export finishes.
- Best used for cleanup or restoring temporary state.
For user-facing validation or reporting, prefer the existing Hubs report viewer / export reporting flow rather than console-only warnings when appropriate.
# Debugging
You can debug the addon code with PyCharm or VSCode:
- [Debug with PyCharm](https://code.blender.org/2015/10/debugging-python-code-with-pycharm) **NOTE:** If you are using Blender 2.80+, you need the [updated debugger script](https://github.com/ux3d/random-blender-addons/blob/master/remote_debugger.py)
- [Debug with VSCode](DEBUGGING.md)
# Continuous Integration Tests
To run the tests locally, your system should have a blender executable in the path that launches the desired version of Blender.
The latest version of [Yarn](https://yarnpkg.com/en/) should also be installed.
Then, in the tests folder of this repository, run yarn install, followed by yarn run test.
================================================
FILE: addons/io_hubs_addon/.pylintrc
================================================
[MASTER]
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-whitelist=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.
jobs=1
# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
limit-inference-results=100
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Specify a configuration file.
#rcfile=
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
confidence=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=print-statement,
parameter-unpacking,
unpacking-in-except,
old-raise-syntax,
backtick,
long-suffix,
old-ne-operator,
old-octal-literal,
import-star-module-level,
non-ascii-bytes-literal,
raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
apply-builtin,
basestring-builtin,
buffer-builtin,
cmp-builtin,
coerce-builtin,
execfile-builtin,
file-builtin,
long-builtin,
raw_input-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
no-absolute-import,
old-division,
dict-iter-method,
dict-view-method,
next-method-called,
metaclass-assignment,
indexing-exception,
raising-string,
reload-builtin,
oct-method,
hex-method,
nonzero-method,
cmp-method,
input-builtin,
round-builtin,
intern-builtin,
unichr-builtin,
map-builtin-not-iterating,
zip-builtin-not-iterating,
range-builtin-not-iterating,
filter-builtin-not-iterating,
using-cmp-argument,
eq-without-hash,
div-method,
idiv-method,
rdiv-method,
exception-message-attribute,
invalid-str-codec,
sys-max-int,
bad-python3-import,
deprecated-string-function,
deprecated-str-translate-call,
deprecated-itertools-function,
deprecated-types-field,
next-method-defined,
dict-items-not-iterating,
dict-keys-not-iterating,
dict-values-not-iterating,
deprecated-operator-function,
deprecated-urllib-function,
xreadlines-attribute,
deprecated-sys-function,
exception-escape,
comprehension-escape,
invalid-name,
missing-docstring,
assignment-from-no-return,
import-error,
protected-access
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member
[REPORTS]
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
#msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit
[LOGGING]
# Format style used to check logging format string. `old` means using %
# formatting, while `new` is for `{}` formatting.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package..
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored. Default to name
# with leading underscore.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
# Maximum number of lines in a module.
max-module-lines=1000
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,
dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[SIMILARITIES]
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
# Minimum lines number of a similarity.
min-similarity-lines=4
[BASIC]
# Naming style matching correct argument names.
argument-naming-style=snake_case
# Regular expression matching correct argument names. Overrides argument-
# naming-style.
#argument-rgx=
# Naming style matching correct attribute names.
attr-naming-style=snake_case
# Regular expression matching correct attribute names. Overrides attr-naming-
# style.
#attr-rgx=
# Bad variable names which should always be refused, separated by a comma.
bad-names=foo,
bar,
baz,
toto,
tutu,
tata
# Naming style matching correct class attribute names.
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style.
#class-attribute-rgx=
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-
# style.
#class-rgx=
# Naming style matching correct constant names.
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names. Overrides const-naming-
# style.
#const-rgx=
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming style matching correct function names.
function-naming-style=snake_case
# Regular expression matching correct function names. Overrides function-
# naming-style.
#function-rgx=
# Good variable names which should always be accepted, separated by a comma.
good-names=i,
j,
k,
ex,
Run,
_
# Include a hint for the correct naming format with invalid-name.
include-naming-hint=no
# Naming style matching correct inline iteration names.
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style.
#inlinevar-rgx=
# Naming style matching correct method names.
method-naming-style=snake_case
# Regular expression matching correct method names. Overrides method-naming-
# style.
#method-rgx=
# Naming style matching correct module names.
module-naming-style=snake_case
# Regular expression matching correct module names. Overrides module-naming-
# style.
#module-rgx=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
# These decorators are taken in consideration only for invalid-name.
property-classes=abc.abstractproperty
# Naming style matching correct variable names.
variable-naming-style=snake_case
# Regular expression matching correct variable names. Overrides variable-
# naming-style.
#variable-rgx=
[STRING]
# This flag controls whether the implicit-str-concat-in-sequence should
# generate a warning on implicit string concatenation in sequences defined over
# several lines.
check-str-concat-over-line-jumps=no
[IMPORTS]
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=optparse,tkinter.tix
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled).
ext-import-graph=
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled).
import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
_fields,
_replace,
_source,
_make
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=cls
[DESIGN]
# Maximum number of arguments for function / method.
max-args=5
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Maximum number of boolean expressions in an if statement.
max-bool-expr=5
# Maximum number of branch for function / method body.
max-branches=12
# Maximum number of locals for function / method body.
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body.
max-returns=6
# Maximum number of statements in function / method body.
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "BaseException, Exception".
overgeneral-exceptions=BaseException,
Exception
================================================
FILE: addons/io_hubs_addon/__init__.py
================================================
from .utils import create_prefs_dir
import sys
import bpy
from .io import gltf_exporter, gltf_importer, panels
from . import (nodes, components)
from . import preferences
from . import third_party
from . import debugger
from . import icons
bl_info = {
"name": "Hubs Blender Addon",
"author": "The Hubs Community",
"description": "Tools for developing glTF assets for Hubs",
"blender": (3, 1, 2),
"version": (1, 8, 0, "dev_build"),
"location": "",
"wiki_url": "https://github.com/Hubs-Foundation/hubs-blender-exporter",
"tracker_url": "https://github.com/Hubs-Foundation/hubs-blender-exporter/issues",
"support": "COMMUNITY",
"warning": "",
"category": "Generic"
}
create_prefs_dir()
# Blender 4.2+ glTF Extension Import/Export Settings Panel
def draw(context, layout):
layout_header, layout_body = layout.panel('HBA_PT_Import_Export_Panel', default_closed=True)
sfile = context.space_data
operator = sfile.active_operator
# Panel Header
if operator.bl_idname == "EXPORT_SCENE_OT_gltf":
props = bpy.context.scene.HubsComponentsExtensionProperties
elif operator.bl_idname == "IMPORT_SCENE_OT_gltf":
props = bpy.context.scene.HubsComponentsExtensionImportProperties
layout_header.use_property_split = False
layout_header.prop(props, 'enabled', text="")
layout_header.label(text="Hubs Components")
# Panel Body
if layout_body:
if operator.bl_idname == "EXPORT_SCENE_OT_gltf":
gltf_exporter.HubsGLTFExportPanel.draw_body(context, layout_body)
elif operator.bl_idname == "IMPORT_SCENE_OT_gltf":
gltf_importer.HubsGLTFImportPanel.draw_body(context, layout_body)
def register():
icons.register()
preferences.register()
nodes.register()
components.register()
gltf_importer.register()
gltf_exporter.register()
panels.register_panels()
third_party.register()
debugger.register()
# Migrate components if the add-on is enabled in the middle of a session.
if bpy.context.preferences.is_dirty:
def registration_migration():
# Passing True as the first argument of the operator forces an undo step to be created.
bpy.ops.wm.migrate_hubs_components(
'EXEC_DEFAULT', True, is_registration=True)
bpy.app.timers.register(registration_migration)
def unregister():
third_party.unregister()
panels.unregister_panels()
gltf_exporter.unregister()
gltf_importer.unregister()
components.unregister()
nodes.unregister()
preferences.unregister()
debugger.unregister()
icons.unregister()
# called by gltf-blender-io after it has loaded
glTF2ExportUserExtension = gltf_exporter.glTF2ExportUserExtension
glTF2_pre_export_callback = gltf_exporter.glTF2_pre_export_callback
glTF2_post_export_callback = gltf_exporter.glTF2_post_export_callback
if bpy.app.version > (3, 0, 0):
glTF2ImportUserExtension = gltf_importer.glTF2ImportUserExtension
def register_panel():
return panels.register_panels()
================================================
FILE: addons/io_hubs_addon/api.py
================================================
import requests
def create_room(endpoint, token=None, scene_name=None, scene_id=None):
payload = {}
if scene_id:
payload = {
"hub": {
"name": scene_name,
"scene_id": scene_id
}
}
headers = {}
if token:
headers = {
"content-type": "application/json",
"authorization": f'Bearer {token}'
}
import json
body = json.dumps(payload)
url = f'{endpoint}/api/v1/hubs'
resp = requests.post(url, body, headers=headers)
return resp.json()
def upload_media(endpoint, file):
resp = requests.post(f'{endpoint}/api/v1/media', files={'media': (
'glb', file, 'application/octet-stream')}, verify=False)
json = resp.json()
if "error" in json:
raise Exception(f'Unknown error')
return {
"file_id": json.get("file_id"),
"access_token": json.get("meta").get("access_token")
}
def publish_scene(endpoint, token, scene_data, scene_id=None):
headers = {
"content-type": "application/json",
"authorization": f'Bearer {token}'
}
import json
body = json.dumps({"scene": scene_data})
url = f'{endpoint}/api/v1/scenes{"/" + scene_id if scene_id else ""}'
if scene_id:
resp = requests.put(url, body, headers=headers)
else:
resp = requests.post(url, body, headers=headers)
jsonFile = resp.json()
if "error" in jsonFile:
error = jsonFile.get("error")
if error == "invalid_token":
raise Exception("Authentication error")
else:
raise Exception(f'Unknown error: {error}')
return jsonFile
def get_projects(endpoint, token):
headers = {
"content-type": "application/json",
"authorization": f'Bearer {token}'
}
resp = requests.get(
f'{endpoint}/api/v1/scenes/projectless', headers=headers)
jsonFile = resp.json()
if "error" in jsonFile:
error = jsonFile.get("error")
if error == "invalid_token":
raise Exception("Authentication error")
else:
raise Exception(f'Unknown error: {error}')
if "scenes" not in jsonFile:
raise Exception(f'Projects request error')
scenes = jsonFile.get("scenes")
return scenes
================================================
FILE: addons/io_hubs_addon/components/__init__.py
================================================
from . import (handlers, gizmos, components_registry, ui, operators, utils)
def register():
utils.register()
handlers.register()
gizmos.register()
components_registry.register()
operators.register()
ui.register()
def unregister():
ui.unregister()
operators.unregister()
components_registry.unregister()
gizmos.unregister()
handlers.unregister()
utils.unregister()
================================================
FILE: addons/io_hubs_addon/components/components_registry.py
================================================
from .types import NodeType
import bpy
from bpy.props import BoolProperty, StringProperty, CollectionProperty, PointerProperty
from bpy.types import PropertyGroup
import importlib
import inspect
import os
from os.path import join, isfile, isdir, dirname, realpath
from .hubs_component import HubsComponent
class HubsComponentName(PropertyGroup):
# For backwards compatibility reasons this attribute is called "name" but it actually points to the component id
name: StringProperty(name="name")
expanded: BoolProperty(name="expanded", default=True)
isDependency: BoolProperty(name="dependency", default=False)
class HubsComponentList(PropertyGroup):
items: CollectionProperty(type=HubsComponentName)
def get_components_in_dir(dir):
components = []
for f in os.listdir(dir):
f_path = join(dir, f)
if isfile(f_path) and f.endswith(".py"):
components.append(f[:-3])
elif isdir(f_path) and f != "__pycache__":
comps = [f + '.' + name for name in get_components_in_dir(f_path)]
components = components + comps
return sorted(components)
def get_user_component_names():
component_names = []
from ..preferences import get_addon_pref
addon_prefs = get_addon_pref(bpy.context)
for entry in addon_prefs.user_components_paths:
if entry.path and os.path.isdir(entry.path):
component_names.append(get_components_in_dir(entry.path))
return component_names
def get_user_component_paths():
component_paths = []
from ..preferences import get_addon_pref
addon_prefs = get_addon_pref(bpy.context)
for entry in addon_prefs.user_components_paths:
if entry.path and os.path.isdir(entry.path):
components = get_components_in_dir(entry.path)
for component in components:
component_paths.append(os.path.join(entry.path, component + ".py"))
return component_paths
def get_user_component_definitions():
modules = []
component_paths = get_user_component_paths()
for component_path in component_paths:
try:
spec = importlib.util.spec_from_file_location(component_path, component_path)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
modules.append(mod)
except Exception as e:
print(f'Failed import of component {component_path}', e)
return modules
def get_component_definitions():
components_dir = join(dirname(realpath(__file__)), "definitions")
component_module_names = get_components_in_dir(components_dir)
return [
importlib.import_module(".definitions." + name, package=__package__)
for name in component_module_names
]
def get_component_module_name(component_class):
relative_module_name = component_class.__module__.replace(f"{__package__}.definitions.", "")
return ".".join(relative_module_name.split(".")[:-1])
def register_component(component_class):
component_module_name = get_component_module_name(component_class)
if component_module_name:
print(f"Registering component: {component_module_name} - {component_class.get_name()}")
else:
print(f"Registering component: {component_class.get_name()}")
bpy.utils.register_class(component_class)
component_id = component_class.get_id()
if component_class.get_node_type() == NodeType.SCENE:
setattr(
bpy.types.Scene,
component_id,
PointerProperty(type=component_class)
)
elif component_class.get_node_type() == NodeType.NODE:
setattr(
bpy.types.Object,
component_id,
PointerProperty(type=component_class)
)
setattr(
bpy.types.Bone,
component_id,
PointerProperty(type=component_class)
)
setattr(
bpy.types.EditBone,
component_id,
PointerProperty(type=component_class)
)
elif component_class.get_node_type() == NodeType.MATERIAL:
setattr(
bpy.types.Material,
component_id,
PointerProperty(type=component_class)
)
from ..io.gltf_exporter import glTF2ExportUserExtension
glTF2ExportUserExtension.add_excluded_property(component_class.get_id())
def unregister_component(component_class):
component_id = component_class.get_id()
if component_class.get_node_type() == NodeType.SCENE:
delattr(bpy.types.Scene, component_id)
elif component_class.get_node_type() == NodeType.NODE:
delattr(bpy.types.Object, component_id)
delattr(bpy.types.Bone, component_id)
delattr(bpy.types.EditBone, component_id)
elif component_class.get_node_type() == NodeType.MATERIAL:
delattr(bpy.types.Material, component_id)
bpy.utils.unregister_class(component_class)
from ..io.gltf_exporter import glTF2ExportUserExtension
glTF2ExportUserExtension.remove_excluded_property(component_class.get_id())
component_module_name = get_component_module_name(component_class)
if component_module_name:
print(f"Component unregistered: {component_module_name} - {component_class.get_name()}")
else:
print(f"Component unregistered: {component_class.get_name()}")
def load_user_components():
global __components_registry
for module in get_user_component_definitions():
for _, member in inspect.getmembers(module):
if inspect.isclass(member) and issubclass(member, HubsComponent) and module.__name__ == member.__module__:
try:
if hasattr(module, 'register_module'):
module.register_module()
register_component(member)
__components_registry[member.get_name()] = member
except Exception:
import traceback
traceback.print_exc()
def unload_user_components():
global __components_registry
for _, component_class in __components_registry.items():
for module_name in get_user_component_names():
if module_name == component_class.get_name():
unregister_component(component_class)
for module in get_user_component_definitions():
if hasattr(module, 'unregister_module'):
module.unregister_module()
def load_components_registry():
"""Recurse in the components directory to build the components registry"""
global __components_registry
__components_registry = {}
for module in get_component_definitions():
for _, member in inspect.getmembers(module):
if inspect.isclass(member) and issubclass(member, HubsComponent) and module.__name__ == member.__module__:
if hasattr(module, 'register_module'):
module.register_module()
register_component(member)
__components_registry[member.get_name()] = member
# When running Blender in factory startup mode and specifying an addon, that addon's register function is called.
# As preferences are not available until the addon is enabled, the user component load fails when accessing them.
# This happens when running tests and this guard avoids crashing in that scenario.
from ..utils import is_addon_enabled
if is_addon_enabled():
load_user_components()
def unload_components_registry():
"""Recurse in the components directory to unload the registered components"""
global __components_registry
for _, component_class in __components_registry.items():
unregister_component(component_class)
for module in get_component_definitions():
if hasattr(module, 'unregister_module'):
module.unregister_module()
__components_registry = {}
def get_components_registry():
global __components_registry
return __components_registry
def get_component_by_name(component_name):
global __components_registry
return next(
(component_class for _, component_class in __components_registry.items()
if component_class.get_name() == component_name),
None)
def register():
load_components_registry()
bpy.utils.register_class(HubsComponentName)
bpy.utils.register_class(HubsComponentList)
bpy.types.Object.hubs_component_list = PointerProperty(
type=HubsComponentList)
bpy.types.Scene.hubs_component_list = PointerProperty(
type=HubsComponentList)
bpy.types.Material.hubs_component_list = PointerProperty(
type=HubsComponentList)
bpy.types.Bone.hubs_component_list = PointerProperty(
type=HubsComponentList)
bpy.types.EditBone.hubs_component_list = PointerProperty(
type=HubsComponentList)
from ..io.gltf_exporter import glTF2ExportUserExtension
glTF2ExportUserExtension.add_excluded_property("hubs_component_list")
def unregister():
del bpy.types.Object.hubs_component_list
del bpy.types.Scene.hubs_component_list
del bpy.types.Material.hubs_component_list
del bpy.types.Bone.hubs_component_list
del bpy.types.EditBone.hubs_component_list
bpy.utils.unregister_class(HubsComponentName)
bpy.utils.unregister_class(HubsComponentList)
from ..io.gltf_exporter import glTF2ExportUserExtension
glTF2ExportUserExtension.remove_excluded_property("hubs_component_list")
unload_components_registry()
global __components_registry
del __components_registry
================================================
FILE: addons/io_hubs_addon/components/consts.py
================================================
from math import pi
DISTANCE_MODELS = [("inverse", "Inverse drop off (inverse)",
"Volume will decrease inversely with distance"),
("linear", "Linear drop off (linear)",
"Volume will decrease linearly with distance"),
("exponential", "Exponential drop off (exponential)",
"Volume will decrease expoentially with distance")]
MAX_ANGLE = 2 * pi
PROJECTION_MODE = [("flat", "2D image (flat)", "Image will be shown on a 2D surface"),
("360-equirectangular",
"Spherical (360-equirectangular)", "Image will be shown on a sphere")]
TRANSPARENCY_MODE = [("opaque", "No transparency (opaque)", "Alpha channel will be ignored"),
("blend", "Gradual transparency (blend)",
"Alpha channel will be applied"),
("mask", "Binary transparency (mask)",
"Alpha channel will be used as a threshold between opaque and transparent pixels")]
INTERPOLATION_MODES = [
("linear", "linear", ""),
("quadraticIn", "quadraticIn", ""),
("quadraticOut", "quadraticOut", ""),
("quadraticInOut", "quadraticInOut", ""),
("cubicIn", "cubicIn", ""),
("cubicOut", "cubicOut", ""),
("cubicInOut", "cubicInOut", ""),
("quarticIn", "quarticIn", ""),
("quarticOut", "quarticOut", ""),
("quarticInOut", "quarticInOut", ""),
("quinticIn", "quinticIn", ""),
("quinticOut", "quinticOut", ""),
("quinticInOut", "quinticInOut", ""),
("sinusoidalIn", "sinusoidalIn", ""),
("sinusoidalOut", "sinusoidalOut", ""),
("sinusoidalInOut", "sinusoidalInOut", ""),
("exponentialIn", "exponentialIn", ""),
("exponentialOut", "exponentialOut", ""),
("exponentialInOut", "exponentialIn", ""),
("circularIn", "circularIn", ""),
("circularOut", "circularOut", ""),
("circularInOut", "circularInOut", ""),
("elasticIn", "elasticIn", ""),
("elasticOut", "elasticOut", ""),
("elasticInOut", "elasticInOut", ""),
("backIn", "backIn", ""),
("backOut", "backOut", ""),
("backInOut", "backInOut", ""),
("bounceIn", "bounceIn", ""),
("bounceOut", "bounceOut", ""),
("bounceInOut", "bounceInOut", "")
]
================================================
FILE: addons/io_hubs_addon/components/definitions/ambient_light.py
================================================
from bpy.props import FloatVectorProperty, FloatProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
class AmbientLight(HubsComponent):
_definition = {
'name': 'ambient-light',
'display_name': 'Ambient Light',
'category': Category.LIGHTS,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'LIGHT_HEMI',
'version': (1, 0, 0)
}
color: FloatVectorProperty(name="Color",
description="Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1)
intensity: FloatProperty(name="Intensity",
description="Intensity",
default=1.0)
================================================
FILE: addons/io_hubs_addon/components/definitions/ammo_shape.py
================================================
from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, BoolProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from ..utils import get_host_or_parents_scaled
class AmmoShape(HubsComponent):
_definition = {
'name': 'ammo-shape',
'display_name': 'Ammo Shape',
'category': Category.OBJECT,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'SCENE_DATA',
'version': (1, 0, 0)
}
type: EnumProperty(
name="Type", description="Type",
items=[("box", "Box Collider", "A box-shaped primitive collision shape"),
("sphere", "Sphere Collider", "A primitive collision shape which represents a sphere"),
("hull", "Convex Hull",
"A convex hull wrapped around the object's vertices. A good analogy for a convex hull is an elastic membrane or balloon under pressure which is placed around a given set of vertices. When released the membrane will assume the shape of the convex hull"),
("mesh", "Mesh Collider",
"A shape made of the actual vertices of the object. This can be expensive for large meshes")],
default="hull")
# TODO Add conditional UI to show only the required properties per type
fit: EnumProperty(
name="Shape Fitting Mode",
description="Shape fitting mode",
items=[("all", "Automatic fit all", "Automatically match the shape to fit the object's vertices"),
("manual", "Manual fit", "Use the manually specified dimensions to define the shape, ignoring the object's vertices")],
default="all")
halfExtents: FloatVectorProperty(
name="Half Extents",
description="Half dimensions of the collider. (Only used when fit is set to \"manual\" and type is set to \"box\")",
unit='LENGTH',
subtype="XYZ",
default=(0.5, 0.5, 0.5))
minHalfExtent: FloatProperty(
name="Min Half Extent",
description="The minimum size to use when automatically generating half extents. (Only used when fit is set to \"all\" and type is set to \"box\")",
unit="LENGTH",
default=0.0)
maxHalfExtent: FloatProperty(
name="Max Half Extent",
description="The maximum size to use when automatically generating half extents. (Only used when fit is set to \"all\" and type is set to \"box\")",
unit="LENGTH",
default=1000.0)
sphereRadius: FloatProperty(
name="Sphere Radius",
description="Radius of the sphere collider. (Only used when fit is set to \"manual\" and type is set to \"sphere\")",
unit="LENGTH", default=0.5)
offset: FloatVectorProperty(
name="Offset", description="An offset to apply to the collider relative to the object's origin",
unit='LENGTH',
subtype="XYZ",
default=(0.0, 0.0, 0.0))
includeInvisible: BoolProperty(
name="Include Invisible",
description="Include invisible objects when generating a collider. (Only used if \"fit\" is set to \"all\")",
default=False)
def draw(self, context, layout, panel):
super().draw(context, layout, panel)
if get_host_or_parents_scaled(context.object):
col = layout.column()
col.alert = True
col.label(
text="The ammo-shape object, and its parents' scale need to be [1,1,1]", icon='ERROR')
================================================
FILE: addons/io_hubs_addon/components/definitions/audio.py
================================================
from ..models import audio
from ..gizmos import CustomModelGizmo, bone_matrix_world
from bpy.props import BoolProperty, StringProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from .networked import migrate_networked
class Audio(HubsComponent):
_definition = {
'name': 'audio',
'display_name': 'Audio',
'category': Category.MEDIA,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'deps': ['networked', 'audio-params'],
'icon': 'OUTLINER_OB_SPEAKER',
'version': (1, 0, 0)
}
src: StringProperty(
name="Audio URL", description="Audio URL", default='https://example.org/AudioFile.mp3')
autoPlay: BoolProperty(name="Auto Play",
description="Auto Play",
default=True)
controls: BoolProperty(
name="Show controls",
description="When enabled, shows play/pause, skip forward/back, and volume controls when hovering your cursor over it in Hubs",
default=True)
loop: BoolProperty(name="Loop",
description="Loop",
default=True)
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
migrate_networked(host)
return migration_occurred
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
mat = bone_matrix_world(ob, bone)
else:
mat = ob.matrix_world.copy()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(CustomModelGizmo.bl_idname)
gizmo.object = ob
setattr(gizmo, "hubs_gizmo_shape", audio.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.color = (0.8, 0.8, 0.8)
gizmo.alpha = 0.5
gizmo.scale_basis = 1.0
gizmo.hide_select = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
================================================
FILE: addons/io_hubs_addon/components/definitions/audio_params.py
================================================
import bpy
from bpy.props import BoolProperty, FloatProperty, EnumProperty
from ..hubs_component import HubsComponent
from ..types import PanelType, NodeType, MigrationType
from ..utils import is_linked, get_host_reference_message
from ..consts import DISTANCE_MODELS, MAX_ANGLE
from ...io.utils import assign_property
from math import degrees, radians
AUDIO_TYPES = [("pannernode", "Positional audio (pannernode)",
"Volume will change depending on the listener's position relative to the source"),
("stereo", "Background audio (stereo)",
"Volume will be independent of the listener's position")]
class AudioParams(HubsComponent):
_definition = {
'name': 'audio-params',
'display_name': 'Audio Params',
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'version': (1, 0, 1)
}
overrideAudioSettings: BoolProperty(
name="Override Audio Settings",
description="Override Audio Settings",
default=False)
audioType: EnumProperty(
name="Audio Type",
description="Audio Type",
items=AUDIO_TYPES,
default="pannernode")
distanceModel: EnumProperty(
name="Distance Model",
description="Distance Model",
items=DISTANCE_MODELS,
default="inverse")
gain: FloatProperty(
name="Gain",
description="How much to amplify the source audio by",
default=1.0,
min=0.0)
refDistance: FloatProperty(
name="Ref Distance",
description="A double value representing the reference distance for reducing volume as the audio source moves further from the listener. For distances greater than this the volume will be reduced based on rolloffFactor and distanceModel",
subtype="DISTANCE",
unit="LENGTH",
default=1.0,
min=0.0)
rolloffFactor: FloatProperty(
name="Rolloff Factor",
description="A double value describing how quickly the volume is reduced as the source moves away from the listener. This value is used by all distance models",
default=1.0,
min=0.0)
maxDistance: FloatProperty(
name="Max Distance",
description="A double value representing the maximum distance between the audio source and the listener, after which the volume is not reduced any further. This value is used only by the linear distance model",
subtype="DISTANCE",
unit="LENGTH",
default=10000.0,
min=0.0)
coneInnerAngle: FloatProperty(
name="Cone Inner Angle",
description="A double value describing the angle, in degrees, of a cone inside of which there will be no volume reduction",
subtype="ANGLE",
default=MAX_ANGLE,
min=0.0,
max=MAX_ANGLE,
precision=2)
coneOuterAngle: FloatProperty(
name="Cone Outer Angle",
description="A double value describing the angle, in degrees, of a cone outside of which the volume will be reduced by a constant value, defined by the coneOuterGain attribute",
subtype="ANGLE",
default=0.0,
min=0.0,
max=MAX_ANGLE,
precision=2)
coneOuterGain: FloatProperty(
name="Cone Outer Gain",
description="A double value describing the amount of volume reduction outside the cone defined by the coneOuterAngle attribute",
default=0.0,
min=0.0,
max=1.0)
def gather(self, export_settings, object):
if (self.overrideAudioSettings):
return {
'audioType': self.audioType,
'distanceModel': self.distanceModel,
'gain': self.gain,
'refDistance': self.refDistance,
'rolloffFactor': self.rolloffFactor,
'maxDistance': self.maxDistance,
'coneInnerAngle': round(degrees(self.coneInnerAngle), 2),
'coneOuterAngle': round(degrees(self.coneOuterAngle), 2),
'coneOuterGain': self.coneOuterGain
}
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
self.coneInnerAngle = radians(
self.coneInnerAngle)
self.coneOuterAngle = radians(
self.coneOuterAngle)
if migration_type != MigrationType.GLOBAL or is_linked(ob) or type(ob) is bpy.types.Armature:
host_reference = get_host_reference_message(panel_type, host, ob=ob)
migration_report.append(
f"Warning: The Media Cone angles may not have migrated correctly for the Audio Params component on the {panel_type.value} {host_reference}")
if instance_version <= (1, 0, 0):
if self.get("overrideAudioSettings") is None:
migration_occurred = True
self.overrideAudioSettings = True
return migration_occurred
def draw(self, context, layout, panel):
layout.prop(data=self, property="overrideAudioSettings")
if not self.overrideAudioSettings:
return
layout.prop(data=self, property="audioType")
layout.prop(data=self, property="gain")
if self.audioType == "pannernode":
layout.prop(data=self, property="distanceModel")
layout.prop(data=self, property="rolloffFactor")
layout.prop(data=self, property="refDistance")
layout.prop(data=self, property="maxDistance")
layout.prop(data=self, property="coneInnerAngle")
layout.prop(data=self, property="coneOuterAngle")
layout.prop(data=self, property="coneOuterGain")
@classmethod
def gather_import(cls, gltf, blender_host, component_name, component_value, import_report, blender_ob=None):
component = blender_host.hubs_component_audio_params
component.overrideAudioSettings = True
for property_name, property_value in component_value.items():
if property_name in ['coneInnerAngle', 'coneOuterAngle']:
property_value = radians(property_value)
assign_property(gltf.vnodes, component,
property_name, property_value)
================================================
FILE: addons/io_hubs_addon/components/definitions/audio_settings.py
================================================
import bpy
from bpy.props import FloatProperty, EnumProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType, MigrationType
from ..utils import is_linked
from ..consts import DISTANCE_MODELS, MAX_ANGLE
from ...io.utils import import_component, assign_property
from math import degrees, radians
class AudioSettings(HubsComponent):
_definition = {
'name': 'audio-settings',
'display_name': 'Audio Settings',
'category': Category.SCENE,
'node_type': NodeType.SCENE,
'panel_type': [PanelType.SCENE],
'icon': 'SPEAKER',
'version': (1, 0, 0)
}
avatarDistanceModel: EnumProperty(
name="Avatar Distance Model",
description="Avatar Distance Model",
items=DISTANCE_MODELS,
default="inverse")
avatarRolloffFactor: FloatProperty(
name="Avatar Rolloff Factor",
default=2.0,
min=0.0)
avatarRefDistance: FloatProperty(
name="Avatar Ref Distance",
description="Avatar Ref Distance",
subtype="DISTANCE",
default=1.0,
min=0.0)
avatarMaxDistance: FloatProperty(
name="Avatar Max Distance",
description="Avatar Max Distance",
subtype="DISTANCE",
default=10000.0,
min=0.0)
mediaVolume: FloatProperty(
name="Media Volume",
description="Media Volume",
default=0.5,
min=0.0)
mediaDistanceModel: EnumProperty(
name="Media Distance Model",
description="Media Distance Model",
items=DISTANCE_MODELS,
default="inverse")
mediaRolloffFactor: FloatProperty(
name="Media Rolloff Factor",
description="Media Rolloff Factor",
default=2.0,
min=0.0)
mediaRefDistance: FloatProperty(
name="Media Ref Distance",
description="Media Rolloff Factor",
subtype="DISTANCE",
default=2.0,
min=0.0)
mediaMaxDistance: FloatProperty(
name="Media Max Distance",
description="Media Max Distance",
subtype="DISTANCE",
default=10000.0,
min=0.0)
mediaConeInnerAngle: FloatProperty(
name="Media Cone Inner Angle",
description="Media Cone Inner Angle",
subtype="ANGLE",
default=MAX_ANGLE,
min=0.0,
max=MAX_ANGLE)
mediaConeOuterAngle: FloatProperty(
name="Media Cone Outer Angle",
description="Media Cone Outer Angle",
subtype="ANGLE",
default=0.0,
min=0.0,
max=MAX_ANGLE)
mediaConeOuterGain: FloatProperty(
name="Media Cone Outer Gain",
description="Media Cone Outer Gain",
default=0.0,
min=0.0,
max=1.0)
def gather(self, export_settings, object):
return {
'avatarDistanceModel': self.avatarDistanceModel,
'avatarRolloffFactor': self.avatarRolloffFactor,
'avatarRefDistance': self.avatarRefDistance,
'avatarMaxDistance': self.avatarMaxDistance,
'mediaVolume': self.mediaVolume,
'mediaDistanceModel': self.mediaDistanceModel,
'mediaRolloffFactor': self.mediaRolloffFactor,
'mediaRefDistance': self.mediaRefDistance,
'mediaMaxDistance': self.mediaMaxDistance,
'mediaConeInnerAngle': round(degrees(self.mediaConeInnerAngle), 2),
'mediaConeOuterAngle': round(degrees(self.mediaConeOuterAngle), 2),
'mediaConeOuterGain': self.mediaConeOuterGain,
}
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
self.mediaConeInnerAngle = radians(
self.mediaConeInnerAngle)
self.mediaConeOuterAngle = radians(
self.mediaConeOuterAngle)
if migration_type != MigrationType.GLOBAL or is_linked(host):
migration_report.append(
f"Warning: The Media Cone angles may not have migrated correctly for the Audio Settings component on scene \"{host.name_full}\"")
return migration_occurred
@classmethod
def gather_import(cls, gltf, blender_host, component_name, component_value, import_report, blender_ob=None):
component = import_component(component_name, blender_host)
for property_name, property_value in component_value.items():
if property_name in ['mediaConeInnerAngle', 'mediaConeOuterAngle']:
property_value = radians(property_value)
assign_property(gltf.vnodes, component,
property_name, property_value)
================================================
FILE: addons/io_hubs_addon/components/definitions/audio_source.py
================================================
from bpy.props import BoolProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
class AudioSource(HubsComponent):
_definition = {
'name': 'zone-audio-source',
'display_name': 'Audio Source',
'category': Category.MEDIA,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'MOD_WAVE',
'version': (1, 0, 0)
}
onlyMods: BoolProperty(
name="Only Mods", description="Only room moderators are able to transmit audio from this source", default=True)
muteSelf: BoolProperty(
name="Mute Self", description="Do not transmit your own audio to audio targets", default=True)
debug: BoolProperty(
name="Debug", description="Play white noise when no audio source is in the zone", default=False)
================================================
FILE: addons/io_hubs_addon/components/definitions/audio_target.py
================================================
from email.policy import default
from bpy.props import FloatProperty, BoolProperty, PointerProperty, EnumProperty, StringProperty
from ..hubs_component import HubsComponent
from ..utils import has_component, is_linked
from ..types import Category, PanelType, NodeType
from ..ui import add_link_indicator
from bpy.types import Object
from ...utils import delayed_gather
from ...io.utils import import_component, assign_property
from .audio_source import AudioSource
BLANK_ID = "374e54CMHFCipSk"
def filter_on_component(self, ob):
dep_name = AudioSource.get_name()
if hasattr(ob, 'type') and ob.type == 'ARMATURE':
if ob.mode == 'EDIT':
ob.update_from_editmode()
for bone in ob.data.bones:
if has_component(bone, dep_name):
return True
return has_component(ob, dep_name)
bones = []
def get_bones(self, context):
global bones
bones = []
count = 0
dep_name = AudioSource.get_name()
bones.append((BLANK_ID, "Select a bone", "None", "BLANK", count))
count += 1
if self.srcNode and self.srcNode.mode == 'EDIT':
self.srcNode.update_from_editmode()
found = False
if self.srcNode and self.srcNode.type == 'ARMATURE':
for bone in self.srcNode.data.bones:
if has_component(bone, dep_name):
bones.append((bone.name, bone.name, "", 'BONE_DATA', count))
count += 1
if bone.name == self.bone_id:
found = True
if self.bone_id != BLANK_ID and not found:
bones.append(
(self.bone_id, self.bone_id, "", "ERROR", count))
count += 1
return bones
def get_bone(self):
global bones
list_ids = list(map(lambda x: x[0], bones))
if self.bone_id in list_ids:
return list_ids.index(self.bone_id)
return 0
def set_bone(self, value):
global bones
list_indexes = list(map(lambda x: x[4], bones))
if value in list_indexes:
self.bone_id = bones[value][0]
else:
self.bone_id = BLANK_ID
class AudioTarget(HubsComponent):
_definition = {
'name': 'audio-target',
'display_name': 'Audio Target',
'category': Category.MEDIA,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'deps': ['audio-params'],
'icon': 'SPEAKER',
'version': (1, 0, 0)
}
srcNode: PointerProperty(
name="Source",
description="The object with an audio-source component to pull audio from",
type=Object,
poll=filter_on_component,
update=lambda self, context: setattr(self, 'bone', BLANK_ID)
)
bone: EnumProperty(
name="Bone",
description="The bone with an audio-source component to pull audio from. If a bone is selected, this will override the object source, otherwise if no bone is selected, the source will be pulled from the object",
items=get_bones,
get=get_bone,
set=set_bone
)
bone_id: StringProperty(
name="bone_id",
default=BLANK_ID,
options={'HIDDEN'})
minDelay: FloatProperty(
name="Min Delay",
description="Minimum random delay applied to the source audio",
default=0.01,
min=0.0)
maxDelay: FloatProperty(
name="Max Delay",
description="Maximum random delay applied to the source audio",
default=0.03,
min=0.0)
debug: BoolProperty(
name="Debug",
description="Show debug visuals",
default=False)
@classmethod
def init(cls, obj):
obj.hubs_component_audio_params.overrideAudioSettings = True
def draw(self, context, layout, panel):
dep_name = AudioSource.get_name()
has_obj_component = False
has_bone_component = False
row = layout.row(align=True)
sub_row = row.row(align=True)
sub_row.prop(data=self, property="srcNode")
if is_linked(context.active_object):
# Manually disable the PointerProperty, needed for Blender 3.2+.
sub_row.enabled = False
if is_linked(self.srcNode):
sub_row = row.row(align=True)
sub_row.enabled = False
add_link_indicator(sub_row, self.srcNode)
if hasattr(self.srcNode, 'type'):
has_obj_component = has_component(self.srcNode, dep_name)
if self.srcNode.type == 'ARMATURE':
layout.prop(data=self, property="bone")
if self.bone_id != BLANK_ID and self.bone in self.srcNode.data.bones:
has_bone_component = has_component(
self.srcNode.data.bones[self.bone], dep_name)
if self.srcNode and self.bone_id == BLANK_ID and not has_obj_component:
col = layout.column()
col.alert = True
col.label(
text=f'The selected source doesn\'t have an {AudioSource.get_display_name()} component', icon='ERROR')
elif self.srcNode and self.bone_id != BLANK_ID and not has_bone_component:
col = layout.column()
col.alert = True
col.label(
text=f'The selected bone doesn\'t have an {AudioSource.get_display_name()} component', icon='ERROR')
layout.prop(data=self, property="minDelay")
layout.prop(data=self, property="maxDelay")
layout.prop(data=self, property="debug")
@delayed_gather
def gather(self, export_settings, object):
from ...io.utils import gather_joint_property, gather_node_property
return {
'srcNode': gather_joint_property(export_settings, self.srcNode, self, 'bone') if self.bone_id != BLANK_ID else gather_node_property(
export_settings, object, self, 'srcNode'),
'maxDelay': self.maxDelay,
'minDelay': self.minDelay,
'debug': self.debug
}
@classmethod
def gather_import(cls, gltf, blender_host, component_name, component_value, import_report, blender_ob=None):
component = import_component(component_name, blender_host)
for property_name, property_value in component_value.items():
if property_name == "srcNode" and type(property_value) is int:
# This srcNode property was generated from an older version of the exporter which stored the index directly as an integer.
property_value = {"__mhc_link_type": "node", "index": property_value}
assign_property(gltf.vnodes, component,
property_name, property_value)
================================================
FILE: addons/io_hubs_addon/components/definitions/audio_zone.py
================================================
from bpy.props import BoolProperty
from ..gizmos import CustomModelGizmo, bone_matrix_world
from ..models import box
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from .networked import migrate_networked
class AudioZone(HubsComponent):
_definition = {
'name': 'audio-zone',
'display_name': 'Audio Zone',
'category': Category.MEDIA,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'deps': ['networked', 'audio-params'],
'icon': 'MATCUBE',
'version': (1, 0, 0)
}
inOut: BoolProperty(
name="In Out",
description="The zone audio parameters affect the sources inside the zone when the listener is outside",
default=True)
outIn: BoolProperty(
name="Out In",
description="The zone audio parameters affect the sources outside the zone when the listener is inside",
default=True)
dynamic: BoolProperty(
name="Dynamic",
description="Whether or not this audio-zone will be movable",
default=False)
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
mat = bone_matrix_world(ob, bone)
else:
mat = ob.matrix_world.copy()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(CustomModelGizmo.bl_idname)
gizmo.object = ob
setattr(gizmo, "hubs_gizmo_shape", box.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.line_width = 3
gizmo.color = (0.0, 0.8, 0.0)
gizmo.alpha = 1.0
gizmo.hide_select = True
gizmo.scale_basis = 1.0
gizmo.color_highlight = (0.0, 0.8, 0.0)
gizmo.alpha_highlight = 0.5
return gizmo
@classmethod
def init(cls, obj):
obj.hubs_component_audio_params.overrideAudioSettings = True
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
migrate_networked(host)
return migration_occurred
================================================
FILE: addons/io_hubs_addon/components/definitions/billboard.py
================================================
from bpy.props import BoolProperty
from ..hubs_component import HubsComponent
from ..types import Category, NodeType, PanelType
class Billboard(HubsComponent):
_definition = {
'name': 'billboard',
'display_name': 'Billboard',
'category': Category.OBJECT,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'IMAGE_PLANE',
'version': (1, 0, 0)
}
onlyY: BoolProperty(
name="Vertical Axis Only",
description="Locks the Vertical Axis to enable only side to side movement in world space and removes any other rotational transforms",
default=False)
================================================
FILE: addons/io_hubs_addon/components/definitions/directional_light.py
================================================
from ..models import directional_light
from ..gizmos import CustomModelGizmo, bone_matrix_world, update_gizmos
from bpy.props import FloatVectorProperty, FloatProperty, BoolProperty, IntVectorProperty
from ..hubs_component import HubsComponent
from ..types import Category, NodeType, PanelType
class DirectionalLight(HubsComponent):
_definition = {
'name': 'directional-light',
'display_name': 'Directional Light',
'category': Category.LIGHTS,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'LIGHT_SUN',
'version': (1, 0, 0)
}
color: FloatVectorProperty(name="Color",
description="Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1,
update=lambda self, context: update_gizmos())
intensity: FloatProperty(name="Intensity",
description="Intensity",
default=1.0)
castShadow: BoolProperty(name="Cast Shadow", default=True)
shadowMapResolution: IntVectorProperty(name="Shadow Map Resolution",
description="Shadow Map Resolution",
size=2,
default=[512, 512])
shadowBias: FloatProperty(name="Shadow Bias",
description="Shadow Bias",
default=0.0)
shadowRadius: FloatProperty(name="Shadow Radius",
description="Shadow Radius",
default=1.0)
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
mat = bone_matrix_world(ob, bone)
else:
mat = ob.matrix_world.copy()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(CustomModelGizmo.bl_idname)
gizmo.object = ob
setattr(gizmo, "hubs_gizmo_shape", directional_light.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.color = getattr(ob, cls.get_id()).color[:3]
gizmo.alpha = 0.5
gizmo.scale_basis = 1.0
gizmo.hide_select = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
================================================
FILE: addons/io_hubs_addon/components/definitions/environment_settings.py
================================================
from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, PointerProperty, BoolProperty
from bpy.types import Image
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from ..utils import is_linked
from ..ui import add_link_indicator
from ...io.utils import import_component, assign_property
import bpy
TOME_MAPPING = [("NoToneMapping", "None", "No tone mapping"),
("LinearToneMapping", "Linear", "Linear tone mapping"),
("ReinhardToneMapping", "ThreeJS 'Reinhard'",
"ThreeJS 'Reinhard' tone mapping"),
("CineonToneMapping", "ThreeJS 'Cineon'",
"ThreeJS 'Cineon' tone mapping"),
("ACESFilmicToneMapping", "ThreeJS 'ACES Filmic'",
"ThreeJS 'ACES Filmic' tone mapping"),
("LUTToneMapping", "Blender 'Filmic'", "Match Blender's Filmic tone mapping")]
class EnvironmentSettings(HubsComponent):
_definition = {
'name': 'environment-settings',
'display_name': 'Environment Settings',
'category': Category.SCENE,
'node_type': NodeType.SCENE,
'panel_type': [PanelType.SCENE],
'icon': 'WORLD',
'version': (1, 0, 0)
}
toneMapping: EnumProperty(
name="Tone Mapping",
description="Tone Mapping",
items=TOME_MAPPING,
default="LUTToneMapping")
toneMappingExposure: FloatProperty(
name="Exposure", description="Exposure level of tone mapping", default=1.0, min=0.0)
backgroundColor: FloatVectorProperty(name="Background Color",
description="Background Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1)
backgroundTexture: PointerProperty(
name="Background Image",
description="An equirectangular image to use as the scene background",
type=Image
)
envMapTexture: PointerProperty(
name="EnvMap",
description="An equirectangular image to use as the default environment map for all objects",
type=Image
)
enableHDRPipeline: BoolProperty(
name="Enable HDR Pipeline",
description="Enable the new (experimental) HDR render pipeline with post processing effects and modified lighting + tonemapping model. NOTE: This checkbox is an opt-in to breaking changes. New versions of the Hubs client may break scenes with this option checked without warning and may reqquire re-export with a later Blender exporter.",
default=False
)
enableBloom: BoolProperty(
name="Bloom",
description="Add a Bloom effect to bright objects.",
default=False
)
bloomThreshold: FloatProperty(
name="Threshold",
description="Values brighter than this in the final render (before tone mapping) will have bloom applied to them. The threshold is applied starting at 1, so a value of 0 will cover all 'HDR' values. You can specify a number below 0 to have bloom effect SDR values (not recommended)",
default=1.0, min=0.0, soft_min=1.0)
bloomIntensity: FloatProperty(
name="Intensity", description="Scales the intensity of the bloom effect", default=1.0, min=0.0)
bloomRadius: FloatProperty(
name="Radius", description="Spread distance of the bloom effect", default=0.6, min=0.0, soft_max=1.0)
bloomSmoothing: FloatProperty(name="Smoothing",
description="Makes transition between under/over-threshold more gradual.",
default=0.025, min=0.0, soft_max=1.0)
def draw(self, context, layout, panel):
layout.prop(data=self, property="enableHDRPipeline")
layout.prop(data=self, property="backgroundColor")
row = layout.row(align=True)
sub_row = row.row(align=True)
sub_row.prop(data=self, property="backgroundTexture")
if is_linked(context.scene):
# Manually disable the PointerProperty, needed for Blender 3.2+.
sub_row.enabled = False
if is_linked(self.backgroundTexture):
sub_row = row.row(align=True)
sub_row.enabled = False
add_link_indicator(sub_row, self.backgroundTexture)
row.context_pointer_set("target", self)
row.context_pointer_set("host", context.scene)
op = row.operator("image.hubs_open_image", text='', icon='FILE_FOLDER')
op.target_property = "backgroundTexture"
row = layout.row(align=True)
sub_row = row.row(align=True)
sub_row.prop(data=self, property="envMapTexture")
if is_linked(context.scene):
# Manually disable the PointerProperty, needed for Blender 3.2+.
sub_row.enabled = False
if is_linked(self.envMapTexture):
sub_row = row.row(align=True)
sub_row.enabled = False
add_link_indicator(sub_row, self.envMapTexture)
row.context_pointer_set("target", self)
row.context_pointer_set("host", context.scene)
op = row.operator("image.hubs_open_image", text='', icon='FILE_FOLDER')
op.target_property = "envMapTexture"
layout.prop(data=self, property="toneMapping")
layout.prop(data=self, property="toneMappingExposure")
if self.enableHDRPipeline:
layout = layout.box()
top_row = layout.row()
top_row.prop(data=self, property="enableBloom")
if self.enableBloom:
layout.prop(data=self, property="bloomThreshold")
layout.prop(data=self, property="bloomIntensity")
layout.prop(data=self, property="bloomRadius")
layout.prop(data=self, property="bloomSmoothing")
def gather(self, export_settings, object):
from ...io.utils import gather_texture_property, gather_color_property
output = {
'toneMapping': self.toneMapping,
'toneMappingExposure': self.toneMappingExposure,
'backgroundColor': gather_color_property(export_settings, object, self, 'backgroundColor', 'COLOR_GAMMA'),
'backgroundTexture': gather_texture_property(
export_settings,
object,
self,
'backgroundTexture'),
'envMapTexture': gather_texture_property(
export_settings,
object,
self,
'envMapTexture')
}
if self.enableHDRPipeline:
output["enableHDRPipeline"] = True
if self.enableBloom:
output["enableBloom"] = True
output["bloom"] = {
"threshold": self.bloomThreshold,
"intensity": self.bloomIntensity,
"radius": self.bloomRadius,
"smoothing": self.bloomSmoothing,
}
return output
@classmethod
def gather_import(cls, gltf, blender_host, component_name, component_value, import_report, blender_ob=None):
component = import_component(component_name, blender_host)
for property_name, property_value in component_value.items():
if property_name == "bloom":
for subproperty_name, subproperty_value in property_value.items():
assign_property(gltf.vnodes, component,
f"bloom{subproperty_name.capitalize()}",
subproperty_value)
else:
assign_property(gltf.vnodes, component,
property_name, property_value)
================================================
FILE: addons/io_hubs_addon/components/definitions/fog.py
================================================
from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
class Fog(HubsComponent):
_definition = {
'name': 'fog',
'display_name': 'Fog',
'category': Category.SCENE,
'node_type': NodeType.SCENE,
'panel_type': [PanelType.SCENE],
'icon': 'MOD_OCEAN',
'version': (1, 0, 0)
}
def draw(self, context, layout, panel):
'''Draw method to be called by the panel.'''
layout.prop(data=self, property="type")
layout.prop(data=self, property="color")
if self.type == "linear":
layout.prop(data=self, property="near")
layout.prop(data=self, property="far")
else:
layout.prop(data=self, property="density")
type: EnumProperty(
name="type",
description="Fog Type",
items=[("linear", "Linear fog", "Fog effect will increase linearly with distance"),
("exponential", "Exponential fog",
"Fog effect will increase exponentially with distance")],
default="linear")
color: FloatVectorProperty(name="Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1)
near: FloatProperty(
name="Near", description="Fog Near Distance (linear only)", default=1.0)
far: FloatProperty(
name="Far", description="Fog Far Distance (linear only)", default=100.0)
density: FloatProperty(
name="Density", description="Fog Density (exponential only)", default=0.00025)
================================================
FILE: addons/io_hubs_addon/components/definitions/frustrum.py
================================================
from bpy.props import BoolProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
class Frustrum(HubsComponent):
_definition = {
'name': 'frustrum',
'display_name': 'Frustum',
'category': Category.OBJECT,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT],
'icon': 'IMAGE_PLANE',
'version': (1, 0, 0)
}
culled: BoolProperty(
name="Culled",
description="Ignore entities outside of the camera frustum. Frustum culling can cause problems with some animations",
default=True)
================================================
FILE: addons/io_hubs_addon/components/definitions/hemisphere_light.py
================================================
from bpy.props import FloatVectorProperty, FloatProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
class HemisphereLight(HubsComponent):
_definition = {
'name': 'hemisphere-light',
'display_name': 'Hemisphere Light',
'category': Category.LIGHTS,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'LIGHT_AREA',
'version': (1, 0, 0)
}
skyColor: FloatVectorProperty(name="Sky Color",
description="Sky Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1)
groundColor: FloatVectorProperty(name="Ground Color",
description="Ground Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1)
intensity: FloatProperty(name="Intensity",
description="Intensity",
default=1.0)
================================================
FILE: addons/io_hubs_addon/components/definitions/image.py
================================================
from ..models import image
from ..gizmos import CustomModelGizmo, bone_matrix_world
from bpy.props import EnumProperty, FloatProperty, StringProperty, BoolProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from ..consts import PROJECTION_MODE, TRANSPARENCY_MODE
from .networked import migrate_networked
class Image(HubsComponent):
_definition = {
'name': 'image',
'display_name': 'Image',
'category': Category.MEDIA,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'FILE_IMAGE',
'deps': ['networked'],
'version': (1, 0, 0)
}
src: StringProperty(
name="Image URL", description="The web address of the image", default="https://example.org/ImageFile.webp")
controls: BoolProperty(
name="Controls",
description="When enabled, shows an \"open link\" button when hovering your cursor over it in Hubs that allows you to open the image in a new tab",
default=True)
alphaMode: EnumProperty(
name="Transparency Mode",
description="Transparency Mode",
items=TRANSPARENCY_MODE,
default="opaque")
alphaCutoff: FloatProperty(
name="Alpha Cutoff",
description="Pixels with alpha values lower than this will be transparent on Binary transparency mode",
default=0.5,
min=0.0,
max=1.0)
projection: EnumProperty(
name="Projection",
description="Projection",
items=PROJECTION_MODE,
default="flat")
def draw(self, context, layout, panel_type):
layout.prop(self, "src")
layout.prop(self, "controls")
layout.prop(self, "alphaMode")
if self.alphaMode == "mask":
layout.prop(self, "alphaCutoff")
layout.prop(self, "projection")
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
migrate_networked(host)
return migration_occurred
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
mat = bone_matrix_world(ob, bone)
else:
mat = ob.matrix_world.copy()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(CustomModelGizmo.bl_idname)
gizmo.object = ob
setattr(gizmo, "hubs_gizmo_shape", image.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.color = (0.8, 0.8, 0.8)
gizmo.alpha = 0.5
gizmo.scale_basis = 1.0
gizmo.hide_select = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
================================================
FILE: addons/io_hubs_addon/components/definitions/link.py
================================================
from ..models import link
from ..gizmos import CustomModelGizmo, bone_matrix_world
from bpy.props import StringProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from .networked import migrate_networked
class Link(HubsComponent):
_definition = {
'name': 'link',
'display_name': 'Link',
'category': Category.ELEMENTS,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'LINKED',
'deps': ['networked'],
'version': (1, 0, 0)
}
href: StringProperty(name="Link URL", description="Link URL",
default="https://example.org")
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
migrate_networked(host)
return migration_occurred
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
mat = bone_matrix_world(ob, bone)
else:
mat = ob.matrix_world.copy()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(CustomModelGizmo.bl_idname)
gizmo.object = ob
setattr(gizmo, "hubs_gizmo_shape", link.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.color = (0.8, 0.8, 0.8)
gizmo.alpha = 0.5
gizmo.scale_basis = 1.0
gizmo.hide_select = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
================================================
FILE: addons/io_hubs_addon/components/definitions/loop_animation.py
================================================
import bpy
from bpy.app.handlers import persistent
from bpy.props import StringProperty, CollectionProperty, IntProperty, EnumProperty, FloatProperty
from bpy.types import PropertyGroup, Menu, Operator
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from ...io.utils import import_component, assign_property
from ..utils import redraw_component_ui, get_host_reference_message
from ...utils import delayed_gather
msgbus_owners = []
class TrackPropertyType(PropertyGroup):
name: StringProperty(
name="Display Name",
description="Display Name",
)
track_name: StringProperty( # Will only contain data if the track references an NLA track
name="Track Name",
description="Track Name",
)
strip_name: StringProperty( # Will only contain data if the track references an NLA track and the NLA track name is generic
name="Strip Name",
description="Strip Name",
)
action_name: StringProperty( # Will only contain data if the NLA track name is generic or the track references an action
name="Action Name",
description="Action Name",
)
track_type: EnumProperty(
name="Track Type",
description="Track Type",
items=[
("object", "Object", "Object"),
("shape_key", "Shape Key", "Shape Key")
],
default="object"
)
class Errors():
_errors = {}
@classmethod
def log(cls, track, error_type, error_message, severity='Error'):
has_error = cls._errors.get(track.track_type + track.name, '')
if not has_error:
cls._errors[track.track_type + track.name] = {
'type': error_type, 'message': error_message, 'severity': severity}
@classmethod
def get(cls, track):
return cls._errors.get(track.track_type + track.name, '')
@classmethod
def clear(cls):
cls._errors.clear()
@classmethod
def are_present(cls):
return bool(cls._errors)
@classmethod
def display_error(cls, layout, error):
message_lines = error['message'].split('\n')
padding = layout.row(align=False)
padding.scale_y = 0.18
padding.label()
for i, line in enumerate(message_lines):
error_row = layout.row(align=False)
error_row.scale_y = 0.7
if i == 0:
error_row.label(
text=f"{error['severity']}: {line}", icon='ERROR')
else:
error_row.label(text=line, icon='BLANK1')
padding = layout.row(align=False)
padding.scale_y = 0.2
padding.label()
def register_msgbus():
global msgbus_owners
if msgbus_owners:
return
for animtype in [bpy.types.NlaTrack, bpy.types.NlaStrip, bpy.types.Action]:
owner = object()
msgbus_owners.append(owner)
bpy.msgbus.subscribe_rna(
key=(animtype, "name"),
owner=owner,
args=(bpy.context,),
notify=redraw_component_ui,
)
def unregister_msgbus():
global msgbus_owners
for owner in msgbus_owners:
bpy.msgbus.clear_by_owner(owner)
msgbus_owners.clear()
@persistent
def load_post(dummy):
unregister_msgbus()
register_msgbus()
@persistent
def undo_redo_post(dummy):
unregister_msgbus()
register_msgbus()
def is_default_name(track_name):
return bool(track_name.startswith("NlaTrack") or track_name.startswith("[Action Stash]"))
def get_display_name(track_name, strip_name):
return track_name if not is_default_name(track_name) else f"{track_name} ({strip_name})"
def get_strip_name(nla_track):
try:
return nla_track.strips[0].name
except IndexError:
return ''
def get_action_name(nla_track):
try:
return nla_track.strips[0].action.name
except (IndexError, AttributeError):
return ''
def get_menu_id(nla_track, track_type, display_name):
return display_name if not is_default_name(nla_track.name) else track_type + display_name
def is_unique_action(animation_data, target_nla_track):
try:
target_action = target_nla_track.strips[0].action
except (IndexError):
return True
for nla_track in animation_data.nla_tracks:
if nla_track == target_nla_track:
continue
try:
action = nla_track.strips[0].action
except (IndexError):
continue
if action == target_action:
return False
return True
def has_track(tracks_list, nla_track, invalid_track=None):
strip_name = get_strip_name(nla_track)
action_name = get_action_name(nla_track)
exists = False
for track in tracks_list:
if is_default_name(nla_track.name):
if track.track_name == nla_track.name and track.strip_name == strip_name and track.action_name == action_name:
exists = True
break
else:
if track.track_name == nla_track.name and track != invalid_track:
exists = True
break
return exists
def has_action(tracks_list, action, invalid_action=None):
exists = False
for track in tracks_list:
if track.name == action.name and track != invalid_action:
exists = True
break
return exists
def action_has_nla_track(ob, action):
nla_tracks_with_action = []
for nla_track in ob.animation_data.nla_tracks:
track_action_name = get_action_name(nla_track)
if track_action_name == action.name:
nla_tracks_with_action.append(nla_track.name)
if hasattr(ob.data, 'shape_keys') and ob.data.shape_keys and ob.data.shape_keys.animation_data:
for nla_track in ob.data.shape_keys.animation_data.nla_tracks:
track_action_name = get_action_name(nla_track)
if track_action_name == action.name:
nla_tracks_with_action.append(nla_track.name)
return any(nla_tracks_with_action)
def is_matching_track(nla_track_type, nla_track, track):
if nla_track_type != track.track_type:
return False
if is_default_name(nla_track.name):
if nla_track.name == track.track_name:
if get_strip_name(nla_track) == track.strip_name:
if get_action_name(nla_track) == track.action_name:
return True
Errors.log(track, 'INVALID_ACTION',
"The action has changed for this strip/track.\nChoose the track again to update.")
else:
if nla_track.name == track.track_name:
return True
return False
def is_useable_nla_track(animation_data, nla_track, track):
# Error checking is handled from top level to bottom level, if something isn't present an error is logged and we return early. This way we always know that the expected constructs are present, e.g. we verify X is valid, then all checks for properties of X are conducted afterwards and we know they won't crash.
track_name = nla_track.name
action_name = get_action_name(nla_track)
if track_name == '':
Errors.log(track, 'FORBIDDEN_NAME', "Track names can't be nothing.")
return False
forbidden_chars = [",", " "]
if not is_default_name(track_name):
if any([c for c in forbidden_chars if c in track_name]):
Errors.log(track, 'FORBIDDEN_NAME',
"Custom track names can't contain commas or spaces.")
return False
else:
if any([c for c in forbidden_chars if c in action_name]):
Errors.log(track, 'FORBIDDEN_NAME',
"Action names can't contain commas or spaces.")
return False
if not nla_track.strips:
Errors.log(track, 'NO_NLA_TRACK_STRIPS', "No strips are present in the NLA track.")
return False
if len(nla_track.strips) > 1:
Errors.log(track, 'MULTIPLE_NLA_TRACK_STRIPS',
"Only one strip is allowed in the NLA track.")
return False
if nla_track.strips[0].mute:
Errors.log(track, 'MUTED_NLA_TRACK_STRIP',
"The NLA track strip is muted and won't export.")
return False
if not action_name:
Errors.log(track, 'NO_ACTION',
"The NLA track strip doesn't have an action.")
return False
action = nla_track.strips[0].action
nla_track_fcurves = None
if bpy.app.version >= (4, 4, 0):
if not action.slots:
Errors.log(track, 'NO_ACTION_SLOTS', "No slots are present in the action.")
return False
if not nla_track.strips[0].action_slot:
Errors.log(track, 'NO_ACTION_SLOT_IN_STRIP', "No action slot has been selected for the NLA track strip.")
return False
if not action.layers:
# Action layers aren't exposed in anything but the Python API as of Blender 5.0
Errors.log(track, 'NO_ACTION_LAYERS',
"The action doesn't have any layers.\nDid you forget to add any keyframes to the action?")
return False
if not action.layers[0].strips:
# Action strips aren't exposed in anything but the Python API as of Blender 5.0
Errors.log(track, 'NO_ACTION_STRIPS', "No strips are present in the action layer.")
return False
channelbag = action.layers[0].strips[0].channelbag(nla_track.strips[0].action_slot)
if channelbag:
nla_track_fcurves = channelbag.fcurves
else:
nla_track_fcurves = action.fcurves
if not nla_track_fcurves:
if bpy.app.version >= (4, 4, 0):
Errors.log(
track, 'NO_FCURVES',
"The NLA track strip's action doesn't have any animation in\nthe active slot and won't be exported.")
else:
Errors.log(track, 'NO_FCURVES',
"The NLA track strip's action doesn't have any animation and\nwon't be exported.")
return False
if not is_unique_action(animation_data, nla_track):
Errors.log(
track, 'NON_UNIQUE_ACTION',
"The NLA track strip contains an action that is present within\nmultiple NLA tracks on this object and may not export correctly.",
severity="Warning")
return False
return True
def is_usable_action(ob, track):
action_name = track.name
action = ob.animation_data.action
action_fcurves = None
if action_name == '':
Errors.log(track, 'FORBIDDEN_NAME', "Action names can't be nothing.")
return False
forbidden_chars = [",", " "]
if any([c for c in forbidden_chars if c in action_name]):
Errors.log(track, 'FORBIDDEN_NAME', "Custom action names can't contain commas or spaces.")
return False
if bpy.app.version >= (4, 4, 0):
if not action.slots:
Errors.log(track, 'NO_ACTION_SLOTS', "No slots are present in the action.")
return False
if not action.layers:
# Action layers aren't exposed in anything but the Python API as of Blender 5.0
Errors.log(track, 'NO_ACTION_LAYERS',
"The action doesn't have any layers.\nDid you forget to add any keyframes to the action?")
return False
if not action.layers[0].strips:
# Action strips aren't exposed in anything but the Python API as of Blender 5.0
Errors.log(track, 'NO_ACTION_STRIPS', "No strips are present in the action layer.")
return False
try:
active_slot = [slot for slot in action.slots if ob in slot.users()][0]
channelbag = action.layers[0].strips[0].channelbag(active_slot)
if channelbag:
action_fcurves = channelbag.fcurves
except IndexError:
Errors.log(track, 'NO_ACTIVE_ACTION_SLOT', "No active slot is present in the action.")
return False
else:
action_fcurves = action.fcurves
if not action_fcurves:
if bpy.app.version >= (4, 4, 0):
Errors.log(track, 'NO_FCURVES',
"The action doesn't have any animation in\nthe active slot and won't be exported.")
else:
Errors.log(track, 'NO_FCURVES',
"The action doesn't have any animation and\nwon't be exported.")
return False
return True
def is_valid_regular_action(ob, track):
if ob.animation_data and ob.animation_data.action and is_usable_action(ob, track):
action = ob.animation_data.action
return not action_has_nla_track(ob, action) and track.name == action.name
return False
def is_valid_regular_nla_track(ob, track):
if ob.animation_data:
for nla_track in ob.animation_data.nla_tracks:
if is_matching_track("object", nla_track, track):
return is_useable_nla_track(ob.animation_data, nla_track, track)
return False
def is_valid_regular_track(ob, track):
if is_valid_regular_nla_track(ob, track):
return True
elif is_valid_regular_action(ob, track):
return True
Errors.log(track, 'NOT_FOUND', "Track not found. Did you mean:")
return False
def is_valid_shape_key_action(ob, track):
if hasattr(ob.data, 'shape_keys') and ob.data.shape_keys and ob.data.shape_keys.animation_data.action:
if is_usable_action(track):
action = ob.data.shape_keys.animation_data.action
return not action_has_nla_track(ob, action) and track.name == action.name
return False
def is_valid_shape_key_nla_track(ob, track):
if hasattr(ob.data, 'shape_keys') and ob.data.shape_keys and ob.data.shape_keys.animation_data:
for nla_track in ob.data.shape_keys.animation_data.nla_tracks:
if is_matching_track("shape_key", nla_track, track):
return is_useable_nla_track(ob.data.shape_keys.animation_data, nla_track, track)
return False
def is_valid_shape_key_track(ob, track):
if is_valid_shape_key_nla_track(ob, track):
return True
elif is_valid_shape_key_action(ob, track):
return True
Errors.log(track, 'NOT_FOUND', "Track not found. Did you mean:")
return False
def get_animation_name(ob, track, export_settings):
if is_valid_regular_action(ob, track) or is_valid_shape_key_action(ob, track):
return track.name
elif is_valid_regular_nla_track(ob, track) or is_valid_shape_key_nla_track(ob, track):
if bpy.app.version >= (4, 4, 0) and export_settings['gltf_animation_mode'] == 'ACTIONS':
nla_track = ob.animation_data.nla_tracks.get(track.track_name)
return nla_track.strips[0].action.name
else:
return track.track_name if not is_default_name(
track.track_name) else track.action_name
else:
return track.name
def import_tracks(tracks, ob, component):
for track_name in tracks:
try:
nla_track = ob.animation_data.nla_tracks[track_name]
track_type = "object"
except (AttributeError, KeyError):
try:
nla_track = ob.data.shape_keys.animation_data.nla_tracks[track_name]
track_type = "shape_key"
except (AttributeError, KeyError):
track = component.tracks_list.add()
track.name = track_name
continue
if not has_track(component.tracks_list, nla_track):
track = component.tracks_list.add()
strip_name = get_strip_name(nla_track)
action_name = get_action_name(nla_track)
track.name = get_display_name(
nla_track.name, strip_name)
track.track_name = nla_track.name
track.strip_name = strip_name if is_default_name(
nla_track.name) else ''
track.action_name = action_name if is_default_name(
nla_track.name) else ''
track.track_type = track_type
class TracksList(bpy.types.UIList):
bl_idname = "HUBS_UL_TRACKS_list"
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
key_block = item
ob = context.object
if self.layout_type in {'DEFAULT', 'COMPACT'}:
split = layout.split(factor=0.90, align=False)
if item.track_type == "object" and is_valid_regular_track(ob, item):
split.prop(key_block, "name", text="",
emboss=False, icon='OBJECT_DATA')
split.enabled = False
elif item.track_type == "shape_key" and is_valid_shape_key_track(ob, item):
split.prop(key_block, "name", text="",
emboss=False, icon='SHAPEKEY_DATA')
split.enabled = False
else:
spacer = ' ' # needed so the menu arrow doesn't intersect with the name
row = split.row(align=False)
row.emboss = 'NONE'
row.alignment = 'LEFT'
row.context_pointer_set('hubs_component', data)
row.context_pointer_set('track', item)
row.menu(UpdateTrackContextMenu.bl_idname,
text=item.name + spacer, icon='ERROR')
row = split.row(align=True)
row.emboss = 'UI_EMBOSS_NONE_OR_STATUS' if bpy.app.version < (
3, 0, 0) else 'NONE_OR_STATUS'
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
class UpdateTrack(Operator):
bl_idname = "hubs_loop_animation.update_track"
bl_label = "Update the track with a new NLA Track"
bl_options = {'REGISTER', 'UNDO'}
name: StringProperty(
name="Display Name", description="Display Name", default="")
track_name: StringProperty(
name="Track Name", description="Track Name", default="")
strip_name: StringProperty(
name="Strip Name", description="Strip Name", default="")
action_name: StringProperty(
name="Action Name", description="Action Name", default="")
track_type: StringProperty(
name="Track Type", description="Track Type", default="")
def execute(self, context):
track = context.track
track.name = self.name
track.track_name = self.track_name
track.strip_name = self.strip_name
track.action_name = self.action_name
track.track_type = self.track_type
redraw_component_ui(context)
return {'FINISHED'}
class AddTrackOperator(Operator):
bl_idname = "hubs_loop_animation.add_track"
bl_label = "Add Track"
bl_options = {'REGISTER', 'UNDO'}
name: StringProperty(
name="Display Name", description="Display Name", default="")
track_name: StringProperty(
name="Track Name", description="Track Name", default="")
strip_name: StringProperty(
name="Strip Name", description="Strip Name", default="")
action_name: StringProperty(
name="Action Name", description="Action Name", default="")
track_type: StringProperty(
name="Track Type", description="Track Type", default="")
panel_type: StringProperty(name="panel_type")
def execute(self, context):
panel_type = PanelType(self.panel_type)
ob = context.object
host = ob if panel_type == PanelType.OBJECT else context.active_bone
track = host.hubs_component_loop_animation.tracks_list.add()
track.name = self.name
track.track_name = self.track_name
track.strip_name = self.strip_name
track.action_name = self.action_name
track.track_type = self.track_type
num_tracks = len(host.hubs_component_loop_animation.tracks_list)
host.hubs_component_loop_animation.active_track_key = num_tracks - 1
redraw_component_ui(context)
return {'FINISHED'}
def invoke(self, context, event):
return self.execute(context)
class RemoveTrackOperator(Operator):
bl_idname = "hubs_loop_animation.remove_track"
bl_label = "Remove Track"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
if hasattr(context, "panel"):
panel_type = PanelType(context.panel.bl_context)
ob = context.object
host = ob if panel_type == PanelType.OBJECT else context.active_bone
return host.hubs_component_loop_animation.active_track_key != -1
return True
def execute(self, context):
panel_type = PanelType(context.panel.bl_context)
ob = context.object
host = ob if panel_type == PanelType.OBJECT else context.active_bone
active_track_key = host.hubs_component_loop_animation.active_track_key
host.hubs_component_loop_animation.tracks_list.remove(
active_track_key)
if host.hubs_component_loop_animation.active_track_key != 0:
host.hubs_component_loop_animation.active_track_key -= 1
if len(host.hubs_component_loop_animation.tracks_list) == 0:
host.hubs_component_loop_animation.active_track_key = -1
redraw_component_ui(context)
return {'FINISHED'}
class UpdateTrackContextMenu(Menu):
bl_idname = "HUBS_MT_TRACKS_update_track_context_menu"
bl_label = "Update Track"
def draw(self, context):
track = context.track
hubs_component = context.hubs_component
layout = self.layout
no_tracks = True
menu_tracks = []
ob = context.object
error = Errors.get(track)
if error:
Errors.display_error(layout, error)
if error['type'] not in ['NOT_FOUND', 'INVALID_ACTION']:
return
layout.separator()
if ob.animation_data:
for _, nla_track in enumerate(ob.animation_data.nla_tracks):
strip_name = get_strip_name(nla_track)
action_name = get_action_name(nla_track)
display_name = get_display_name(nla_track.name, strip_name)
track_type = "object"
menu_id = get_menu_id(nla_track, track_type, display_name)
if menu_id not in menu_tracks and not has_track(
hubs_component.tracks_list, nla_track, invalid_track=track):
row = layout.row(align=False)
row.context_pointer_set('track', track)
update_track = row.operator(UpdateTrack.bl_idname,
icon='OBJECT_DATA', text=display_name)
update_track.name = display_name
update_track.track_name = nla_track.name
update_track.strip_name = strip_name if is_default_name(
nla_track.name) else ''
update_track.action_name = action_name if is_default_name(
nla_track.name) else ''
update_track.track_type = track_type
no_tracks = False
menu_tracks.append(menu_id)
if ob.animation_data.action:
action = ob.animation_data.action
action_name = action.name
track_type = "object"
menu_id = action_name
if menu_id not in menu_tracks and not action_has_nla_track(ob, action) and not has_action(
hubs_component.tracks_list, action, invalid_action=action):
row = layout.row(align=False)
row.context_pointer_set('track', track)
update_track = row.operator(UpdateTrack.bl_idname,
icon='OBJECT_DATA', text=action_name)
update_track.name = action_name
update_track.action_name = action_name
update_track.track_type = track_type
no_tracks = False
menu_tracks.append(menu_id)
if hasattr(ob.data, 'shape_keys') and ob.data.shape_keys and ob.data.shape_keys.animation_data:
for _, nla_track in enumerate(ob.data.shape_keys.animation_data.nla_tracks):
strip_name = get_strip_name(nla_track)
action_name = get_action_name(nla_track)
display_name = get_display_name(nla_track.name, strip_name)
track_type = "shape_key"
menu_id = get_menu_id(nla_track, track_type, display_name)
if menu_id not in menu_tracks and not has_track(
hubs_component.tracks_list, nla_track, invalid_track=track):
row = layout.row(align=False)
row.context_pointer_set('track', track)
update_track = row.operator(UpdateTrack.bl_idname,
icon='SHAPEKEY_DATA', text=display_name)
update_track.name = display_name
update_track.track_name = nla_track.name
update_track.strip_name = strip_name if is_default_name(
nla_track.name) else ''
update_track.action_name = action_name if is_default_name(
nla_track.name) else ''
update_track.track_type = track_type
no_tracks = False
menu_tracks.append(menu_id)
if ob.data.shape_keys.animation_data.action:
action = ob.data.shape_keys.animation_data.action
action_name = action.name
track_type = "shape_key"
menu_id = action_name
if menu_id not in menu_tracks and not action_has_nla_track(ob, action) and not has_action(
hubs_component.tracks_list, action, invalid_action=action):
row = layout.row(align=False)
row.context_pointer_set('track', track)
update_track = row.operator(UpdateTrack.bl_idname,
icon='SHAPEKEY_DATA', text=action_name)
update_track.name = action_name
update_track.action_name = action_name
update_track.track_type = track_type
no_tracks = False
menu_tracks.append(menu_id)
if no_tracks:
layout.label(text="No tracks found")
class TracksContextMenu(Menu):
bl_idname = "HUBS_MT_TRACKS_context_menu"
bl_label = "Add Track"
def draw(self, context):
panel_type = PanelType(context.panel.bl_context)
layout = self.layout
no_tracks = True
menu_tracks = []
ob = context.object
host = ob if panel_type == PanelType.OBJECT else context.active_bone
component_tracks_list = host.hubs_component_loop_animation.tracks_list
if ob.animation_data:
for _, nla_track in enumerate(ob.animation_data.nla_tracks):
strip_name = get_strip_name(nla_track)
action_name = get_action_name(nla_track)
display_name = get_display_name(nla_track.name, strip_name)
track_type = "object"
menu_id = get_menu_id(nla_track, track_type, display_name)
if menu_id not in menu_tracks and not has_track(component_tracks_list, nla_track):
add_track = layout.operator(AddTrackOperator.bl_idname,
icon='OBJECT_DATA', text=display_name)
add_track.name = display_name
add_track.track_name = nla_track.name
add_track.strip_name = strip_name if is_default_name(
nla_track.name) else ''
add_track.action_name = action_name if is_default_name(
nla_track.name) else ''
add_track.track_type = track_type
add_track.panel_type = panel_type.value
no_tracks = False
menu_tracks.append(menu_id)
if ob.animation_data.action:
action = ob.animation_data.action
action_name = action.name
menu_id = action_name
track_type = "object"
if menu_id not in menu_tracks and not action_has_nla_track(
ob, action) and not has_action(
component_tracks_list, action):
add_track = layout.operator(AddTrackOperator.bl_idname,
icon='OBJECT_DATA', text=action_name)
add_track.name = action_name
add_track.action_name = action_name
add_track.track_type = track_type
add_track.panel_type = panel_type.value
no_tracks = False
menu_tracks.append(menu_id)
if hasattr(ob.data, 'shape_keys') and ob.data.shape_keys and ob.data.shape_keys.animation_data:
for _, nla_track in enumerate(ob.data.shape_keys.animation_data.nla_tracks):
strip_name = get_strip_name(nla_track)
action_name = get_action_name(nla_track)
display_name = get_display_name(nla_track.name, strip_name)
track_type = "shape_key"
menu_id = get_menu_id(nla_track, track_type, display_name)
if menu_id not in menu_tracks and not has_track(component_tracks_list, nla_track):
add_track = layout.operator(AddTrackOperator.bl_idname,
icon='SHAPEKEY_DATA', text=display_name)
add_track.name = display_name
add_track.track_name = nla_track.name
add_track.strip_name = strip_name if is_default_name(
nla_track.name) else ''
add_track.action_name = action_name if is_default_name(
nla_track.name) else ''
add_track.track_type = track_type
add_track.panel_type = panel_type.value
no_tracks = False
menu_tracks.append(menu_id)
if ob.data.shape_keys.animation_data.action:
action = ob.data.shape_keys.animation_data.action
action_name = action.name
menu_id = action_name
track_type = "shape_key"
if menu_id not in menu_tracks and not action_has_nla_track(
ob, action) and not has_action(
component_tracks_list, action):
add_track = layout.operator(AddTrackOperator.bl_idname,
icon='SHAPEKEY_DATA', text=action_name)
add_track.name = action_name
add_track.action_name = action_name
add_track.track_type = track_type
add_track.panel_type = panel_type.value
no_tracks = False
menu_tracks.append(menu_id)
if no_tracks:
layout.label(text="No tracks found")
class LoopAnimation(HubsComponent):
_definition = {
'name': 'loop-animation',
'display_name': 'Loop Animation',
'category': Category.ANIMATION,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'LOOP_BACK',
'version': (1, 1, 0)
}
tracks_list: CollectionProperty(
type=TrackPropertyType)
clip: StringProperty(
name="Animation Clip",
description="Animation clip to use",
default=""
)
active_track_key: IntProperty(
name="Active track index",
description="Active track index",
default=-1
)
startOffset: IntProperty(
name="Start Offset",
description="Time in frames to skip on the first loop of the animation",
default=0
)
timeScale: FloatProperty(
name="Time Scale",
description="Scale animation playback speed by this factor. Normal playback rate being 1. Negative values will play the animation backwards",
default=1.0
)
def draw(self, context, layout, panel):
Errors.clear()
layout.prop(data=self, property="startOffset")
layout.prop(data=self, property="timeScale")
layout.label(text='Animations to play:')
row = layout.row()
row.template_list(TracksList.bl_idname, "", self,
"tracks_list", self, "active_track_key", rows=3)
col = row.column(align=True)
col.context_pointer_set('panel', panel)
col.menu(TracksContextMenu.bl_idname, icon='ADD', text="")
col.operator(RemoveTrackOperator.bl_idname,
icon='REMOVE', text="")
if Errors.are_present():
error_row = layout.row()
error_row.alert = True
error_row.label(text="Errors detected, click on the flagged tracks for more information.",
icon='ERROR')
layout.separator()
def gather(self, export_settings, object):
final_track_names = []
for track in object.hubs_component_loop_animation.tracks_list.values():
final_track_names.append(get_animation_name(object, track, export_settings))
fps = bpy.context.scene.render.fps / bpy.context.scene.render.fps_base
return {
'clip': ",".join(
final_track_names),
'startOffset': self.startOffset / fps,
'timeScale': self.timeScale
}
@staticmethod
def register():
bpy.utils.register_class(TracksList)
bpy.utils.register_class(UpdateTrackContextMenu)
bpy.utils.register_class(TracksContextMenu)
bpy.utils.register_class(UpdateTrack)
bpy.utils.register_class(AddTrackOperator)
bpy.utils.register_class(RemoveTrackOperator)
if load_post not in bpy.app.handlers.load_post:
bpy.app.handlers.load_post.append(load_post)
if undo_redo_post not in bpy.app.handlers.undo_post:
bpy.app.handlers.undo_post.append(undo_redo_post)
if undo_redo_post not in bpy.app.handlers.redo_post:
bpy.app.handlers.redo_post.append(undo_redo_post)
register_msgbus()
@staticmethod
def unregister():
bpy.utils.unregister_class(TracksList)
bpy.utils.unregister_class(UpdateTrackContextMenu)
bpy.utils.unregister_class(TracksContextMenu)
bpy.utils.unregister_class(UpdateTrack)
bpy.utils.unregister_class(AddTrackOperator)
bpy.utils.unregister_class(RemoveTrackOperator)
if load_post in bpy.app.handlers.load_post:
bpy.app.handlers.load_post.remove(load_post)
if undo_redo_post in bpy.app.handlers.undo_post:
bpy.app.handlers.undo_post.remove(undo_redo_post)
if undo_redo_post in bpy.app.handlers.redo_post:
bpy.app.handlers.redo_post.remove(undo_redo_post)
unregister_msgbus()
@classmethod
@delayed_gather
def gather_import(cls, gltf, blender_host, component_name, component_value, import_report, blender_ob=None):
blender_component = import_component(
component_name, blender_host)
for property_name, property_value in component_value.items():
if property_name == 'clip' and property_value != "":
tracks = property_value.split(",")
import_tracks(tracks, blender_ob, blender_component)
else:
if property_name == 'startOffset':
fps = bpy.context.scene.render.fps / bpy.context.scene.render.fps_base
property_value = round(property_value * fps)
assign_property(gltf.vnodes, blender_component,
property_name, property_value)
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
migration_warning = False
tracks = self.clip.split(",")
for track_name in tracks:
nla_track = None
action = None
# check regular
try:
nla_track = ob.animation_data.nla_tracks[track_name]
track_type = "object"
except (AttributeError, KeyError):
try:
action = ob.animation_data.action
if not action_has_nla_track(ob, action) and track_name == action.name:
track_type = "object"
else:
raise KeyError
except (AttributeError, KeyError):
action = None
if not (nla_track or action):
# check shapekey
try:
nla_track = ob.data.shape_keys.animation_data.nla_tracks[track_name]
track_type = "shape_key"
except (AttributeError, KeyError):
try:
action = ob.data.shape_keys.animation_data.action
if not action_has_nla_track(ob, action) and track_name == action.name:
track_type = "shape_key"
else:
raise KeyError
except (AttributeError, KeyError):
action = None
if not (nla_track or action):
# nothing found
track = self.tracks_list.add()
track.name = track_name
migration_warning = True
continue
if nla_track:
if not has_track(self.tracks_list, nla_track):
track = self.tracks_list.add()
strip_name = get_strip_name(nla_track)
action_name = get_action_name(nla_track)
track.name = get_display_name(nla_track.name, strip_name)
track.track_name = nla_track.name
track.strip_name = strip_name if is_default_name(nla_track.name) else ''
track.action_name = action_name if is_default_name(nla_track.name) else ''
track.track_type = track_type
elif action:
if not has_action(self.tracks_list, action):
track = self.tracks_list.add()
track.name = action.name
track.track_name = ''
track.strip_name = ''
track.action_name = action.name
track.track_type = track_type
if migration_warning:
host_reference = get_host_reference_message(panel_type, host, ob=ob)
migration_report.append(
f"Warning: The Loop Animation component on the {panel_type.value} {host_reference} may not have migrated correctly")
return migration_occurred
def register_module():
bpy.utils.register_class(TrackPropertyType)
def unregister_module():
bpy.utils.unregister_class(TrackPropertyType)
================================================
FILE: addons/io_hubs_addon/components/definitions/media_frame.py
================================================
import bpy
from bpy.props import EnumProperty, FloatVectorProperty, BoolProperty
from bpy.types import (Gizmo, Bone, EditBone)
from ..gizmos import bone_matrix_world
from ..models import box
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType, MigrationType
from ..utils import get_host_or_parents_scaled, is_linked, get_host_reference_message
from .networked import migrate_networked
from mathutils import Matrix, Vector
from ...io.utils import import_component, assign_property
def is_bone(ob):
return type(ob) is EditBone or type(ob) is Bone
class MediaFrameGizmo(Gizmo):
"""MediaFrame gizmo"""
bl_idname = "GIZMO_GT_hba_mediaframe_gizmo"
bl_target_properties = (
{"id": "bounds", "type": 'FLOAT', "array_length": 3},
)
__slots__ = (
"hubs_gizmo_shape",
"custom_shape",
)
def _update_offset_matrix(self):
loc, rot, _ = self.matrix_basis.decompose()
scale = self.target_get_value("bounds")
mat_out = Matrix.Translation(
loc) @ rot.normalized().to_matrix().to_4x4() @ Matrix.Diagonal(scale).to_4x4()
self.matrix_basis = mat_out
def draw(self, context):
self._update_offset_matrix()
self.draw_custom_shape(self.custom_shape)
def draw_select(self, context, select_id):
self._update_offset_matrix()
self.draw_custom_shape(self.custom_shape, select_id=select_id)
def setup(self):
if hasattr(self, "hubs_gizmo_shape"):
self.custom_shape = self.new_custom_shape(
'TRIS', self.hubs_gizmo_shape)
class MediaFrame(HubsComponent):
_definition = {
'name': 'media-frame',
'display_name': 'Media Frame',
'category': Category.ELEMENTS,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'OBJECT_DATA',
'deps': ['networked'],
'version': (1, 0, 0)
}
mediaType: EnumProperty(
name="Media Type",
description="Limit what type of media this frame will capture",
items=[("all", "All Media", "Allow any type of media"),
("all-2d", "Only 2D Media", "Allow only Images, Videos, and PDFs"),
("model", "Only 3D Models", "Allow only 3D models"),
("image", "Only Images", "Allow only images"),
("video", "Only Videos", "Allow only videos"),
("pdf", "Only PDFs", "Allow only PDFs")],
default="all-2d")
bounds: FloatVectorProperty(
name="Bounds",
description="Bounding box to fit objects into when they are snapped into the media frame",
unit='LENGTH',
subtype="XYZ",
default=(1.0, 1.0, 1.0))
alignX: EnumProperty(
name="Align X",
description="Media alignment along the X axis",
items=[("min", "Min", "Align minimum X bounds of media and frame"),
("center", "Center", "Align X centers of media and frame"),
("max", "Max", "Align maximum X bounds of media and frame")],
default="center")
alignY: EnumProperty(
name="Align Y",
description="Media alignment along the Y axis",
items=[("min", "Min", "Align minimum Y bounds of media and frame"),
("center", "Center", "Align Y centers of media and frame"),
("max", "Max", "Align maximum Y bounds of media and frame")],
default="center")
alignZ: EnumProperty(
name="Align Z",
description="Media alignment along the Z axis",
items=[("min", "Min", "Align minimum Z bounds of media and frame"),
("center", "Center", "Align Z centers of media and frame"),
("max", "Max", "Align maximum Z bounds of media and frame")],
default="center")
scaleToBounds: BoolProperty(
name="Scale To Bounds",
description="Scale the media to fit within the bounds of the media frame",
default=True
)
snapToCenter: BoolProperty(
name="Snap To Center",
description="Snap the media to the center of the media frame when capturing. If set to false the object will just remain in the place it was dropped but still be considered \"captured\" by the media frame",
default=True
)
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
gizmo.target_set_prop(
"bounds", target.hubs_component_media_frame, "bounds")
scale = gizmo.target_get_value("bounds")
if bone:
mat = bone_matrix_world(ob, bone, scale)
else:
loc, rot, _ = ob.matrix_world.decompose()
mat = Matrix.Translation(
loc) @ rot.normalized().to_matrix().to_4x4() @ Matrix.Diagonal(scale).to_4x4()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(MediaFrameGizmo.bl_idname)
setattr(gizmo, "hubs_gizmo_shape", box.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.color = (0.0, 0.0, 0.8)
gizmo.alpha = 1.0
gizmo.scale_basis = 1.0
gizmo.hide_select = True
gizmo.color_highlight = (0.0, 0.0, 0.8)
gizmo.alpha_highlight = 0.5
gizmo.target_set_prop(
"bounds", ob.hubs_component_media_frame, "bounds")
return gizmo
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
migrate_networked(host)
bounds = self.bounds.copy()
bounds = Vector((bounds.x, bounds.z, bounds.y))
self.bounds = bounds
if migration_type != MigrationType.GLOBAL or is_linked(ob) or type(ob) is bpy.types.Armature:
host_reference = get_host_reference_message(panel_type, host, ob=ob)
migration_report.append(
f"Warning: The Media Frame component's Y and Z bounds on the {panel_type.value} {host_reference} may not have migrated correctly")
return migration_occurred
@staticmethod
def register():
bpy.utils.register_class(MediaFrameGizmo)
@staticmethod
def unregister():
bpy.utils.unregister_class(MediaFrameGizmo)
def gather(self, export_settings, object):
bounds = {
'x': self.bounds.x,
'y': self.bounds.y,
'z': self.bounds.z
}
if export_settings['gltf_yup']:
bounds['y'] = self.bounds.z
bounds['z'] = self.bounds.y
align = {
'x': self.alignX,
'y': self.alignY,
'z': self.alignZ
}
if export_settings['gltf_yup']:
align['y'] = self.alignZ
align['z'] = "min" if self.alignY == "max" else "max" if self.alignY == "min" else self.alignY
return {
'bounds': bounds,
'mediaType': self.mediaType,
'align': align,
'scaleToBounds': self.scaleToBounds,
'snapToCenter': self.snapToCenter
}
def draw(self, context, layout, panel):
super().draw(context, layout, panel)
if get_host_or_parents_scaled(context.object):
col = layout.column()
col.alert = True
col.label(
text="The media-frame object, and its parents' scale need to be [1,1,1]", icon='ERROR')
@classmethod
def gather_import(cls, gltf, blender_host, component_name, component_value, import_report, blender_ob=None):
blender_component = import_component(
component_name, blender_host)
gltf_yup = gltf.import_settings.get('gltf_yup', True)
for property_name, property_value in component_value.items():
if property_name == 'bounds' and gltf_yup:
property_value['y'], property_value['z'] = property_value['z'], property_value['y']
assign_property(gltf.vnodes, blender_component,
property_name, property_value)
elif property_name == 'align':
align = {
'x': property_value['x'],
'y': property_value['y'],
'z': property_value['z']
}
if gltf_yup:
align['y'] = "min" if property_value['z'] == "max" else "max" if property_value['z'] == "min" else property_value['z']
align['z'] = property_value['y']
blender_component.alignX = align['x']
blender_component.alignY = align['y']
blender_component.alignZ = align['z']
else:
assign_property(gltf.vnodes, blender_component,
property_name, property_value)
if get_host_or_parents_scaled(blender_host):
import_report.append(
f"The media-frame {blender_host.name} or one of its parents' scales isn't [1,1,1]. If this file is being imported from Spoke, then you may need to multiply the bounds parameter by the parents' scale before resetting the scale to [1,1,1].")
================================================
FILE: addons/io_hubs_addon/components/definitions/mirror.py
================================================
from bpy.props import FloatVectorProperty
from ..hubs_component import HubsComponent
from ..gizmos import update_gizmos
from ..types import Category, PanelType, NodeType
from mathutils import Matrix, Quaternion
from math import radians
class Mirror(HubsComponent):
_definition = {
'name': 'mirror',
'display_name': 'Mirror',
'category': Category.SCENE,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'MOD_MIRROR',
'version': (1, 0, 0)
}
color: FloatVectorProperty(name="Color",
description="Color",
subtype='COLOR_GAMMA',
default=(0.498039, 0.498039, 0.498039),
size=3,
min=0,
max=1,
update=lambda self, context: update_gizmos())
def draw(self, context, layout, panel_type):
super().draw(context, layout, panel_type)
cmp = getattr(context.object, self.get_id())
if cmp.color[:] == (0.0, 0.0, 0.0):
layout.label(
text="You won't see much if the mirror is black", icon='ERROR')
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new('GIZMO_GT_primitive_3d')
gizmo.draw_style = ('PLANE')
gizmo.use_draw_scale = False
gizmo.use_draw_offset_scale = True
gizmo.line_width = 3
gizmo.color = getattr(ob, cls.get_id()).color[:3]
gizmo.alpha = 0.5
gizmo.hide_select = True
gizmo.scale_basis = 0.5
gizmo.use_draw_modal = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
loc, rot, scale = bone.matrix.to_4x4().decompose()
# Account for bones using Y up
rot_offset = Matrix.Rotation(radians(-90), 4, 'X').to_4x4()
rot = rot.normalized().to_matrix().to_4x4() @ rot_offset
# Account for the armature object's position
loc = ob.matrix_world @ Matrix.Translation(loc)
# Apply the custom rotation
rot_offset = Matrix.Rotation(radians(90), 4, 'X').to_4x4()
rot = rot @ rot_offset
# Shrink the gizmo to a 1x1m square (Blender defaults to 2x2m)
scale = scale / 2
# Convert the scale to a matrix
scale = Matrix.Diagonal(scale).to_4x4()
# Assemble the new matrix
mat_out = loc @ rot @ scale
else:
loc, rot, scale = ob.matrix_world.decompose()
# Apply the custom rotation
offset = Quaternion((1.0, 0.0, 0.0), radians(90.0))
new_rot = rot @ offset
# Shrink the gizmo to a 1x1m square (Blender defaults to 2x2m)
scale = scale / 2
# Assemble the new matrix
mat_out = Matrix.Translation(
loc) @ new_rot.normalized().to_matrix().to_4x4() @ Matrix.Diagonal(scale).to_4x4()
gizmo.matrix_basis = mat_out
gizmo.hide = not ob.visible_get()
================================================
FILE: addons/io_hubs_addon/components/definitions/model.py
================================================
from bpy.props import StringProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from .networked import migrate_networked
class Model(HubsComponent):
_definition = {
'name': 'model',
'display_name': 'Model',
'category': Category.MEDIA,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'SCENE_DATA',
'deps': ['networked'],
'version': (1, 0, 0)
}
src: StringProperty(name="Model URL", description="Model URL",
default="https://example.org/ModelFile.glb")
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
migrate_networked(host)
return migration_occurred
================================================
FILE: addons/io_hubs_addon/components/definitions/morph_audio_feedback.py
================================================
import bpy
from bpy.props import FloatProperty, StringProperty, EnumProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
shape_keys = []
BLANK_ID = "cKsdi5pSEUGvSg8"
def get_object_shape_keys(cmp, ob):
global shape_keys
shape_keys = []
count = 0
shape_keys.append(
(BLANK_ID, "Select a shape key", "None", "BLANK", count))
count += 1
found = False
if ob.data.shape_keys:
for item in ob.data.shape_keys.key_blocks:
if item == item.relative_key:
pass
else:
shape_keys.append(
(item.name, item.name, "", 'SHAPEKEY_DATA', count))
count += 1
if item.name == cmp.name:
found = True
if cmp.name != BLANK_ID and not found:
shape_keys.append(
(cmp.name, cmp.name, "", "ERROR", count))
count += 1
return shape_keys
def get_shape_keys(self, context):
return get_object_shape_keys(self, context.object)
def get_shape_key(self):
global shape_keys
list_ids = list(map(lambda x: x[0], shape_keys))
if self.name in list_ids:
return list_ids.index(self.name)
return 0
def set_shape_key(self, value):
global shape_keys
list_indexes = list(map(lambda x: x[4], shape_keys))
if value in list_indexes:
self.name = shape_keys[value][0]
else:
self.name = BLANK_ID
class MorphAudioFeedback(HubsComponent):
_definition = {
'name': 'morph-audio-feedback',
'display_name': 'Morph Audio Feedback',
'category': Category.AVATAR,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT],
'icon': 'MOD_SMOOTH',
'version': (1, 0, 0)
}
name: StringProperty(
name="Name",
description="Name",
default=BLANK_ID
)
shape_key: EnumProperty(
name="Shape Key",
description="Shape key to morph",
items=get_shape_keys,
get=get_shape_key,
set=set_shape_key
)
minValue: FloatProperty(name="Min Value",
description="Min Value",
default=0.0,)
maxValue: FloatProperty(name="Max Value",
description="Max Value",
default=1.0)
@classmethod
def poll(cls, panel_type, host, ob=None):
return host.type == 'MESH'
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 0):
migration_occurred = True
shape_keys = get_object_shape_keys(self, host)
list_ids = list(map(lambda x: x[0], shape_keys))
if self.name not in list_ids:
self.name = self.name
return migration_occurred
def draw(self, context, layout, panel):
layout.prop(data=self, property="shape_key")
shape_keys = context.object.data.shape_keys
if self.shape_key != BLANK_ID and shape_keys and self.shape_key not in shape_keys.key_blocks:
col = layout.column()
col.alert = True
col.label(text="No matching shape key found",
icon='ERROR')
layout.prop(data=self, property="minValue")
layout.prop(data=self, property="maxValue")
def gather(self, export_settings, object):
return {
'name': self.name if self.name != BLANK_ID else "",
'minValue': self.minValue,
'maxValue': self.maxValue
}
================================================
FILE: addons/io_hubs_addon/components/definitions/nav_mesh.py
================================================
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from ..utils import has_component, add_component
class NavMesh(HubsComponent):
_definition = {
'name': 'nav-mesh',
'display_name': 'Navigation Mesh',
'category': Category.SCENE,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT],
'icon': 'GRID',
'version': (1, 0, 1),
'deps': ['visible']
}
@classmethod
def poll(cls, panel_type, host, ob=None):
return host.type == 'MESH'
def draw(self, context, layout, panel):
ob = context.object
total = 0
if ob.type == 'MESH' and ob.data and ob.data.materials:
for material in ob.data.materials:
if material:
total += 1
if total > 1:
col = layout.column()
col.alert = True
col.label(text='The Nav mesh should only have one material',
icon='ERROR')
@classmethod
def init(cls, obj):
obj.hubs_component_visible.visible = False
obj.hubs_component_list.items.get('visible').isDependency = True
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 0, 1):
if not has_component(host, 'visible'):
add_component(host, 'visible')
host.hubs_component_visible.visible = False
host.hubs_component_list.items.get('visible').isDependency = True
migration_occurred = True
return migration_occurred
================================================
FILE: addons/io_hubs_addon/components/definitions/networked.py
================================================
from ..hubs_component import HubsComponent
from bpy.props import StringProperty
from ..types import PanelType, NodeType
import uuid
from ..utils import add_component
import bpy
class Networked(HubsComponent):
_definition = {
'name': 'networked',
'display_name': 'Networked',
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'version': (1, 0, 0)
}
def gather(self, export_settings, object):
return {
'id': str(uuid.uuid4()).upper()
}
def migrate_networked(host):
if Networked.get_name() not in host.hubs_component_list.items:
add_component(host, Networked.get_name())
================================================
FILE: addons/io_hubs_addon/components/definitions/particle_emitter.py
================================================
from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, StringProperty, IntProperty
from ..hubs_component import HubsComponent
from ..types import Category, NodeType, PanelType, MigrationType
from ..consts import INTERPOLATION_MODES
from ..gizmos import CustomModelGizmo, bone_matrix_world, update_gizmos
from ..models import particle_emitter
from ..utils import is_linked, get_host_reference_message
import bpy
from mathutils import Vector
from ...io.utils import import_component, assign_property
class ParticleEmitter(HubsComponent):
_definition = {
'name': 'particle-emitter',
'display_name': 'Particle Emitter',
'category': Category.ELEMENTS,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'PARTICLES',
'version': (1, 1, 0)
}
particleCount: IntProperty(
name="Particle Count", description="Particle Count", subtype="UNSIGNED", default=100)
src: StringProperty(
name="Image Source", description="The web address (URL) of the image to use for each particle",
default="https://assets.example.org/spoke/assets/images/dot-75db99b125fe4e9afbe58696320bea73.png")
ageRandomness: FloatProperty(
name="Age Randomness", description="Age Randomness", default=10.0)
lifetime: FloatProperty(
name="Lifetime", description="Lifetime", unit="TIME", subtype="TIME", default=5.0)
lifetimeRandomness: FloatProperty(
name="Lifetime Randomness", description="Lifetime Randomness", default=5.0)
sizeCurve: EnumProperty(
name="Size Curve",
description="Size Curve",
items=INTERPOLATION_MODES,
default="linear")
startSize: FloatProperty(
name="Start Size", description="Start Size", default=0.25)
endSize: FloatProperty(
name="End Size", description="End Size", default=0.25)
sizeRandomness: FloatProperty(
name="Size Randomness", description="Size Randomness", default=0.0)
colorCurve: EnumProperty(
name="Color Curve",
description="Color Curve",
items=INTERPOLATION_MODES,
default="linear")
startColor: FloatVectorProperty(name="Start Color",
description="Start Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1,
update=lambda self, context: update_gizmos())
startOpacity: FloatProperty(
name="Start Opacity", description="Start Opacity", default=1.0)
middleColor: FloatVectorProperty(name="Middle Color",
description="Middle Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1)
middleOpacity: FloatProperty(
name="Middle Opacity", description="Middle Opacity", default=1.0)
endColor: FloatVectorProperty(name="End Color",
description="End Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1)
endOpacity: FloatProperty(
name="End Opacity", description="end Opacity", default=1.0)
velocityCurve: EnumProperty(
name="Velocity Curve",
description="Velocity Curve",
items=INTERPOLATION_MODES,
default="linear")
startVelocity: FloatVectorProperty(
name="Start Velocity", description="Start Velocity", unit="LENGTH", subtype="XYZ", default=(0.0, 0.0, 0.5))
endVelocity: FloatVectorProperty(
name="End Velocity", description="End Velocity", unit="LENGTH", subtype="XYZ", default=(0.0, 0.0, 0.5))
angularVelocity: FloatProperty(
name="Angular Velocity", description="Angular Velocity", unit="VELOCITY", default=0.0)
def draw(self, context, layout, panel):
alert_src = getattr(self, "src") == self.bl_rna.properties['src'].default
for key in self.get_properties():
if not self.bl_rna.properties[key].is_hidden:
row = layout.row()
if key == "src" and alert_src:
row.alert = True
row.prop(data=self, property=key)
if key == "src" and alert_src:
warning_row = layout.row()
warning_row.alert = True
warning_row.label(
text="Warning: the default URL won't work unless you replace 'example.org' with the domain of your Hubs instance.",
icon='ERROR')
def gather(self, export_settings, object):
props = super().gather(export_settings, object)
props['startVelocity'] = {
'x': self.startVelocity[0],
'y': self.startVelocity[2] if export_settings['gltf_yup'] else self.startVelocity[1],
'z': self.startVelocity[1] if export_settings['gltf_yup'] else self.startVelocity[2],
}
props['endVelocity'] = {
'x': self.endVelocity[0],
'y': self.endVelocity[2] if export_settings['gltf_yup'] else self.endVelocity[1],
'z': self.endVelocity[1] if export_settings['gltf_yup'] else self.endVelocity[2],
}
return props
def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None):
migration_occurred = False
if instance_version < (1, 1, 0):
migration_occurred = True
startVelocity = self.startVelocity.copy()
startVelocity = Vector((startVelocity.x, startVelocity.z, startVelocity.y))
self.startVelocity = startVelocity
endVelocity = self.endVelocity.copy()
endVelocity = Vector((endVelocity.x, endVelocity.z, endVelocity.y))
self.endVelocity = endVelocity
return migration_occurred
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
mat = bone_matrix_world(ob, bone)
else:
mat = ob.matrix_world.copy()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(CustomModelGizmo.bl_idname)
gizmo.object = ob
setattr(gizmo, "hubs_gizmo_shape", particle_emitter.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.color = getattr(ob, cls.get_id()).startColor[:3]
gizmo.alpha = 0.5
gizmo.scale_basis = 1.0
gizmo.hide_select = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
@classmethod
def gather_import(cls, gltf, blender_host, component_name, component_value, import_report, blender_ob=None):
blender_component = import_component(
component_name, blender_host)
gltf_yup = gltf.import_settings.get('gltf_yup', True)
for property_name, property_value in component_value.items():
if property_name in ['startVelocity', 'endVelocity'] and gltf_yup:
property_value['y'], property_value['z'] = property_value['z'], property_value['y']
assign_property(gltf.vnodes, blender_component,
property_name, property_value)
================================================
FILE: addons/io_hubs_addon/components/definitions/pdf.py
================================================
from bpy.props import StringProperty, BoolProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from mathutils import Matrix
from math import radians
class PDF(HubsComponent):
_definition = {
'name': 'pdf',
'display_name': 'PDF',
'category': Category.MEDIA,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'deps': ['networked'],
'icon': 'FILE_IMAGE',
'version': (1, 0, 0)
}
src: StringProperty(
name="PDF URL", description="The web address of the PDF", default='https://example.org/PdfFile.pdf')
controls: BoolProperty(
name="Controls",
description="When enabled, shows pagination buttons when hovering your cursor over it in Hubs that allow you to switch pages",
default=True)
@classmethod
def gather_name(cls):
return 'image'
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new('GIZMO_GT_primitive_3d')
gizmo.draw_style = ('PLANE')
gizmo.use_draw_scale = False
gizmo.use_draw_offset_scale = True
gizmo.line_width = 3
gizmo.color = (0.8, 0.8, 0.8)
gizmo.alpha = 0.5
gizmo.hide_select = True
gizmo.scale_basis = 0.5
gizmo.use_draw_modal = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
loc, rot, scale = bone.matrix.to_4x4().decompose()
# Account for the armature object's position
loc = ob.matrix_world @ Matrix.Translation(loc)
# Convert to A4 aspect ratio
scale[1] = 1.414
# Shrink the gizmo to fit within a 1x1m square
scale = scale * 0.3538
# Convert the scale to a matrix
scale = Matrix.Diagonal(scale).to_4x4()
# Convert the rotation to a matrix
rot = rot.normalized().to_matrix().to_4x4()
# Assemble the new matrix
mat_out = loc @ rot @ scale
else:
loc, rot, scale = ob.matrix_world.decompose()
# Apply the custom rotation
rot_offset = Matrix.Rotation(radians(90), 4, 'X').to_4x4()
new_rot = rot.normalized().to_matrix().to_4x4() @ rot_offset
# Convert to A4 aspect ratio
scale[1] = 1.414
# Shrink the gizmo to fit within a 1x1m square
scale = scale * 0.3538
# Assemble the new matrix
mat_out = Matrix.Translation(
loc) @ new_rot @ Matrix.Diagonal(scale).to_4x4()
gizmo.matrix_basis = mat_out
gizmo.hide = not ob.visible_get()
================================================
FILE: addons/io_hubs_addon/components/definitions/personal_space_invader.py
================================================
from bpy.props import BoolProperty, FloatProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
class PersonalSpaceInvader(HubsComponent):
_definition = {
'name': 'personal-space-invader',
'display_name': 'Personal Space Invader',
'category': Category.AVATAR,
'node_type': NodeType.NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'MATSHADERBALL',
'version': (1, 0, 0)
}
radius: FloatProperty(name="Radius",
description="Radius",
default=0.1)
useMaterial: BoolProperty(name="Use Material",
description="Use Material",
default=False)
invadingOpacity: FloatProperty(name="Invading Opacity",
description="Invading Opacity",
default=0.3)
================================================
FILE: addons/io_hubs_addon/components/definitions/point_light.py
================================================
from ..models import point_light
from ..gizmos import CustomModelGizmo, bone_matrix_world, update_gizmos
from bpy.props import FloatVectorProperty, FloatProperty, BoolProperty, IntVectorProperty
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
class PointLight(HubsComponent):
_definition = {
'name': 'point-light',
'display_name': 'Point Light',
'category': Category.LIGHTS,
'node_type': NodeType. NODE,
'panel_type': [PanelType.OBJECT, PanelType.BONE],
'icon': 'LIGHT_POINT',
'version': (1, 0, 0)
}
color: FloatVectorProperty(name="Color",
description="Color",
subtype='COLOR_GAMMA',
default=(1.0, 1.0, 1.0, 1.0),
size=4,
min=0,
max=1,
update=lambda self, context: update_gizmos())
intensity: FloatProperty(name="Intensity",
description="Intensity",
default=1.0)
range: FloatProperty(name="Range",
description="Range",
default=0.0)
decay: FloatProperty(name="Decay",
description="Decay",
default=2.0)
castShadow: BoolProperty(
name="Cast Shadow", description="Cast Shadow", default=True)
shadowMapResolution: IntVectorProperty(name="Shadow Map Resolution",
description="Shadow Map Resolution",
size=2,
default=[512, 512])
shadowBias: FloatProperty(name="Shadow Bias",
description="Shadow Bias",
default=0.0)
shadowRadius: FloatProperty(name="Shadow Radius",
description="Shadow Radius",
default=1.0)
@classmethod
def update_gizmo(cls, ob, bone, target, gizmo):
if bone:
mat = bone_matrix_world(ob, bone)
else:
mat = ob.matrix_world.copy()
gizmo.hide = not ob.visible_get()
gizmo.matrix_basis = mat
@classmethod
def create_gizmo(cls, ob, gizmo_group):
gizmo = gizmo_group.gizmos.new(CustomModelGizmo.bl_idname)
gizmo.object = ob
setattr(gizmo, "hubs_gizmo_shape", point_light.SHAPE)
gizmo.setup()
gizmo.use_draw_scale = False
gizmo.use_draw_modal = False
gizmo.color = getattr(ob, cls.get_id()).color[:3]
gizmo.alpha = 0.5
gizmo.scale_basis = 1.0
gizmo.hide_select = True
gizmo.color_highlight = (0.8, 0.8, 0.8)
gizmo.alpha_highlight = 1.0
return gizmo
================================================
FILE: addons/io_hubs_addon/components/definitions/reflection_probe.py
================================================
from ..operators import OpenImage
import bpy
from bpy.props import PointerProperty, EnumProperty, StringProperty, BoolProperty, CollectionProperty
from bpy.types import Image, PropertyGroup, Operator
from ...components.utils import is_gpu_available, redraw_component_ui, is_linked, update_image_editors
from ..components_registry import get_components_registry
from ..hubs_component import HubsComponent
from ..types import Category, PanelType, NodeType
from ..ui import add_link_indicator
from ...utils import rgetattr, rsetattr
from ...io.utils import import_component, assign_property
import math
import os
DEFAULT_RESOLUTION_ITEMS = [
('128x64', '128x64',
'128 x 64', '', 0),
('256x128', '256x128',
'256 x 128', '', 1),
('512x256', '512x256',
'512 x 256', '', 2),
('1024x512', '1024x512',
'1024 x 512', '', 3),
('2048x1024', '2048x1024',
'2048 x 1024', '', 4),
]
RESOLUTION_ITEMS = DEFAULT_RESOLUTION_ITEMS[:]
probe_baking = False
bake_mode = None
def get_resolutions(self, context):
global RESOLUTION_ITEMS
env_map = context.scene.hubs_component_environment_settings.envMapTexture
if env_map:
x = env_map.size[0]
y = env_map.size[1]
RESOLUTION_ITEMS = [(f'{x}x{y}', f'{x}x{y}', f'{x} x {y}', '', 0)]
else:
RESOLUTION_ITEMS = DEFAULT_RESOLUTION_ITEMS
return RESOLUTION_ITEMS
def get_resolution(self):
env_map = bpy.context.scene.hubs_component_environment_settings.envMapTexture
list_ids = [x[0] for x in RESOLUTION_ITEMS]
return 0 if env_map else list_ids.index(self.resolution_id)
def set_resolution(self, value):
env_map = bpy.context.scene.hubs_component_environment_settings.envMapTexture
if not env_map:
self.resolution_id = RESOLUTION_ITEMS[value][0]
def get_probes(all_objects=False, include_locked=False, include_linked=False):
probes = []
objects = bpy.data.objects if all_objects else bpy.context.view_layer.objects
for ob in objects:
component_list = ob.hubs_component_list
registered_hubs_components = get_components_registry()
if component_list.items:
for component_item in component_list.items:
component_name = component_item.name
if component_name in registered_hubs_components:
if component_name == 'reflection-probe':
probe_component = ob.hubs_component
gitextract_dnqs3d2a/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report-blender-add-on.md
│ │ └── feature_request.md
│ └── workflows/
│ ├── publish.yml
│ └── roadmap-auto-commenter.yml
├── .gitignore
├── .vscode/
│ ├── launch.json
│ └── settings.json
├── LICENSE
├── Pipfile
├── README.md
├── addons/
│ └── io_hubs_addon/
│ ├── .pylintrc
│ ├── __init__.py
│ ├── api.py
│ ├── components/
│ │ ├── __init__.py
│ │ ├── components_registry.py
│ │ ├── consts.py
│ │ ├── definitions/
│ │ │ ├── ambient_light.py
│ │ │ ├── ammo_shape.py
│ │ │ ├── audio.py
│ │ │ ├── audio_params.py
│ │ │ ├── audio_settings.py
│ │ │ ├── audio_source.py
│ │ │ ├── audio_target.py
│ │ │ ├── audio_zone.py
│ │ │ ├── billboard.py
│ │ │ ├── directional_light.py
│ │ │ ├── environment_settings.py
│ │ │ ├── fog.py
│ │ │ ├── frustrum.py
│ │ │ ├── hemisphere_light.py
│ │ │ ├── image.py
│ │ │ ├── link.py
│ │ │ ├── loop_animation.py
│ │ │ ├── media_frame.py
│ │ │ ├── mirror.py
│ │ │ ├── model.py
│ │ │ ├── morph_audio_feedback.py
│ │ │ ├── nav_mesh.py
│ │ │ ├── networked.py
│ │ │ ├── particle_emitter.py
│ │ │ ├── pdf.py
│ │ │ ├── personal_space_invader.py
│ │ │ ├── point_light.py
│ │ │ ├── reflection_probe.py
│ │ │ ├── scale_audio_feedback.py
│ │ │ ├── scene_preview_camera.py
│ │ │ ├── shadow.py
│ │ │ ├── simple_water.py
│ │ │ ├── skybox.py
│ │ │ ├── spawner.py
│ │ │ ├── spoke/
│ │ │ │ ├── background.py
│ │ │ │ ├── box_collider.py
│ │ │ │ └── spawn_point.py
│ │ │ ├── spot_light.py
│ │ │ ├── text.py
│ │ │ ├── uv_scroll.py
│ │ │ ├── video.py
│ │ │ ├── video_texture_source.py
│ │ │ ├── video_texture_target.py
│ │ │ ├── visible.py
│ │ │ └── waypoint.py
│ │ ├── gizmos.py
│ │ ├── handlers.py
│ │ ├── hubs_component.py
│ │ ├── models/
│ │ │ ├── audio.py
│ │ │ ├── box.py
│ │ │ ├── directional_light.py
│ │ │ ├── image.py
│ │ │ ├── link.py
│ │ │ ├── particle_emitter.py
│ │ │ ├── point_light.py
│ │ │ ├── scene_preview_camera.py
│ │ │ ├── spawn_point.py
│ │ │ ├── spot_light.py
│ │ │ └── video.py
│ │ ├── operators.py
│ │ ├── types.py
│ │ ├── ui.py
│ │ └── utils.py
│ ├── debugger.py
│ ├── dependencies/
│ │ └── __init__.py
│ ├── hubs_session.py
│ ├── icons.py
│ ├── io/
│ │ ├── gltf_exporter.py
│ │ ├── gltf_importer.py
│ │ ├── panels.py
│ │ └── utils.py
│ ├── nodes/
│ │ ├── __init__.py
│ │ └── lightmap.py
│ ├── preferences.py
│ ├── third_party/
│ │ ├── __init__.py
│ │ └── recast.py
│ └── utils.py
├── check_style.py
├── format.py
├── gizmos/
│ ├── audio.blend
│ ├── box.blend
│ ├── directional_light.blend
│ ├── image.blend
│ ├── link.blend
│ ├── particle_emitter.blend
│ ├── point_light.blend
│ ├── scene_preview_camera.blend
│ ├── spawn_point.blend
│ ├── spot_light.blend
│ └── video.blend
├── scripts/
│ └── export_gizmo.py
├── setup.sh
├── tests/
│ ├── .eslintrc.json
│ ├── .npmrc
│ ├── export_gltf.py
│ ├── package.json
│ ├── roundtrip_gltf.py
│ ├── scenes/
│ │ ├── ambient-light.blend
│ │ ├── ammo-shape.blend
│ │ ├── audio-settings.blend
│ │ ├── audio-target.blend
│ │ ├── audio-zone.blend
│ │ ├── audio.blend
│ │ ├── billboard.blend
│ │ ├── directional-light.blend
│ │ ├── environment-settings.blend
│ │ ├── fog.blend
│ │ ├── frustrum.blend
│ │ ├── hemisphere-light.blend
│ │ ├── image.blend
│ │ ├── lightmap.blend
│ │ ├── link.blend
│ │ ├── loop-animation.blend
│ │ ├── media-frame.blend
│ │ ├── model.blend
│ │ ├── morph-audio-feedback.blend
│ │ ├── nav-mesh.blend
│ │ ├── particle-emitter.blend
│ │ ├── pdf.blend
│ │ ├── personal-space-invader.blend
│ │ ├── point-light.blend
│ │ ├── reflection-probe.blend
│ │ ├── scale-audio-feedback.blend
│ │ ├── shadow.blend
│ │ ├── simple-water.blend
│ │ ├── skybox.blend
│ │ ├── spawner.blend
│ │ ├── spot-light.blend
│ │ ├── text.blend
│ │ ├── text_clip-rect.blend
│ │ ├── uv-scroll.blend
│ │ ├── video-texture.blend
│ │ ├── video.blend
│ │ ├── visible.blend
│ │ └── waypoint.blend
│ └── test/
│ ├── test_export.js
│ ├── tests/
│ │ ├── ambient-light.js
│ │ ├── ammo-shape.js
│ │ ├── audio-settings.js
│ │ ├── audio-target.js
│ │ ├── audio-zone.js
│ │ ├── audio.js
│ │ ├── billboard.js
│ │ ├── directional-light.js
│ │ ├── environment-settings.js
│ │ ├── fog.js
│ │ ├── frustrum.js
│ │ ├── hemisphere-light.js
│ │ ├── image.js
│ │ ├── link.js
│ │ ├── loop-animation.js
│ │ ├── media-frame.js
│ │ ├── model.js
│ │ ├── morph-audio-feedback.js
│ │ ├── nav-mesh.js
│ │ ├── particle-emitter.js
│ │ ├── personal-space-invader.js
│ │ ├── point-light.js
│ │ ├── scale-audio-feedback.js
│ │ ├── shadow.js
│ │ ├── simple-water.js
│ │ ├── skybox.js
│ │ ├── spawner.js
│ │ ├── spot-light.js
│ │ ├── text.js
│ │ ├── text_clip-rect.js
│ │ ├── uv-scroll.js
│ │ ├── video-texture.js
│ │ ├── video.js
│ │ ├── visible.js
│ │ └── waypoint.js
│ └── utils.js
└── third_parties/
└── recast/
├── app/
│ ├── CMakeLists.txt
│ ├── main.cpp
│ ├── mesh_navmesh.cpp
│ ├── mesh_navmesh.h
│ ├── recast-capi.cpp
│ ├── recast-capi.h
│ └── recast-capi_global.h
└── recast/
├── CMakeLists.txt
├── CONTRIBUTING.md
├── License.txt
├── README.md
├── Recast/
│ ├── CMakeLists.txt
│ ├── Include/
│ │ ├── Recast.h
│ │ ├── RecastAlloc.h
│ │ └── RecastAssert.h
│ └── Source/
│ ├── Recast.cpp
│ ├── RecastAlloc.cpp
│ ├── RecastArea.cpp
│ ├── RecastAssert.cpp
│ ├── RecastContour.cpp
│ ├── RecastFilter.cpp
│ ├── RecastLayers.cpp
│ ├── RecastMesh.cpp
│ ├── RecastMeshDetail.cpp
│ ├── RecastRasterization.cpp
│ └── RecastRegion.cpp
└── readme-addon.txt
SYMBOL INDEX (1092 symbols across 91 files)
FILE: addons/io_hubs_addon/__init__.py
function draw (line 29) | def draw(context, layout):
function register (line 52) | def register():
function unregister (line 72) | def unregister():
function register_panel (line 94) | def register_panel():
FILE: addons/io_hubs_addon/api.py
function create_room (line 4) | def create_room(endpoint, token=None, scene_name=None, scene_id=None):
function upload_media (line 30) | def upload_media(endpoint, file):
function publish_scene (line 44) | def publish_scene(endpoint, token, scene_data, scene_id=None):
function get_projects (line 70) | def get_projects(endpoint, token):
FILE: addons/io_hubs_addon/components/__init__.py
function register (line 4) | def register():
function unregister (line 13) | def unregister():
FILE: addons/io_hubs_addon/components/components_registry.py
class HubsComponentName (line 14) | class HubsComponentName(PropertyGroup):
class HubsComponentList (line 21) | class HubsComponentList(PropertyGroup):
function get_components_in_dir (line 25) | def get_components_in_dir(dir):
function get_user_component_names (line 37) | def get_user_component_names():
function get_user_component_paths (line 47) | def get_user_component_paths():
function get_user_component_definitions (line 59) | def get_user_component_definitions():
function get_component_definitions (line 74) | def get_component_definitions():
function get_component_module_name (line 83) | def get_component_module_name(component_class):
function register_component (line 88) | def register_component(component_class):
function unregister_component (line 130) | def unregister_component(component_class):
function load_user_components (line 153) | def load_user_components():
function unload_user_components (line 168) | def unload_user_components():
function load_components_registry (line 179) | def load_components_registry():
function unload_components_registry (line 199) | def unload_components_registry():
function get_components_registry (line 212) | def get_components_registry():
function get_component_by_name (line 217) | def get_component_by_name(component_name):
function register (line 225) | def register():
function unregister (line 246) | def unregister():
FILE: addons/io_hubs_addon/components/definitions/ambient_light.py
class AmbientLight (line 6) | class AmbientLight(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/ammo_shape.py
class AmmoShape (line 7) | class AmmoShape(HubsComponent):
method draw (line 71) | def draw(self, context, layout, panel):
FILE: addons/io_hubs_addon/components/definitions/audio.py
class Audio (line 9) | class Audio(HubsComponent):
method migrate (line 37) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method update_gizmo (line 46) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 56) | def create_gizmo(cls, ob, gizmo_group):
FILE: addons/io_hubs_addon/components/definitions/audio_params.py
class AudioParams (line 16) | class AudioParams(HubsComponent):
method gather (line 95) | def gather(self, export_settings, object):
method migrate (line 109) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method draw (line 130) | def draw(self, context, layout, panel):
method gather_import (line 148) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/audio_settings.py
class AudioSettings (line 11) | class AudioSettings(HubsComponent):
method gather (line 102) | def gather(self, export_settings, object):
method migrate (line 118) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method gather_import (line 134) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/audio_source.py
class AudioSource (line 6) | class AudioSource(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/audio_target.py
function filter_on_component (line 16) | def filter_on_component(self, ob):
function get_bones (line 31) | def get_bones(self, context):
function get_bone (line 59) | def get_bone(self):
function set_bone (line 67) | def set_bone(self, value):
class AudioTarget (line 76) | class AudioTarget(HubsComponent):
method init (line 127) | def init(cls, obj):
method draw (line 130) | def draw(self, context, layout, panel):
method gather (line 170) | def gather(self, export_settings, object):
method gather_import (line 181) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/audio_zone.py
class AudioZone (line 9) | class AudioZone(HubsComponent):
method update_gizmo (line 37) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 47) | def create_gizmo(cls, ob, gizmo_group):
method init (line 65) | def init(cls, obj):
method migrate (line 68) | def migrate(self, migration_type, panel_type, instance_version, host, ...
FILE: addons/io_hubs_addon/components/definitions/billboard.py
class Billboard (line 6) | class Billboard(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/directional_light.py
class DirectionalLight (line 8) | class DirectionalLight(HubsComponent):
method update_gizmo (line 48) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 58) | def create_gizmo(cls, ob, gizmo_group):
FILE: addons/io_hubs_addon/components/definitions/environment_settings.py
class EnvironmentSettings (line 22) | class EnvironmentSettings(HubsComponent):
method draw (line 84) | def draw(self, context, layout, panel):
method gather (line 135) | def gather(self, export_settings, object):
method gather_import (line 168) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/fog.py
class Fog (line 6) | class Fog(HubsComponent):
method draw (line 17) | def draw(self, context, layout, panel):
FILE: addons/io_hubs_addon/components/definitions/frustrum.py
class Frustrum (line 6) | class Frustrum(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/hemisphere_light.py
class HemisphereLight (line 6) | class HemisphereLight(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/image.py
class Image (line 10) | class Image(HubsComponent):
method draw (line 49) | def draw(self, context, layout, panel_type):
method migrate (line 57) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method update_gizmo (line 66) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 76) | def create_gizmo(cls, ob, gizmo_group):
FILE: addons/io_hubs_addon/components/definitions/link.py
class Link (line 9) | class Link(HubsComponent):
method migrate (line 24) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method update_gizmo (line 33) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 43) | def create_gizmo(cls, ob, gizmo_group):
FILE: addons/io_hubs_addon/components/definitions/loop_animation.py
class TrackPropertyType (line 14) | class TrackPropertyType(PropertyGroup):
class Errors (line 42) | class Errors():
method log (line 46) | def log(cls, track, error_type, error_message, severity='Error'):
method get (line 53) | def get(cls, track):
method clear (line 57) | def clear(cls):
method are_present (line 61) | def are_present(cls):
method display_error (line 65) | def display_error(cls, layout, error):
function register_msgbus (line 85) | def register_msgbus():
function unregister_msgbus (line 102) | def unregister_msgbus():
function load_post (line 111) | def load_post(dummy):
function undo_redo_post (line 117) | def undo_redo_post(dummy):
function is_default_name (line 122) | def is_default_name(track_name):
function get_display_name (line 126) | def get_display_name(track_name, strip_name):
function get_strip_name (line 130) | def get_strip_name(nla_track):
function get_action_name (line 137) | def get_action_name(nla_track):
function get_menu_id (line 144) | def get_menu_id(nla_track, track_type, display_name):
function is_unique_action (line 148) | def is_unique_action(animation_data, target_nla_track):
function has_track (line 169) | def has_track(tracks_list, nla_track, invalid_track=None):
function has_action (line 187) | def has_action(tracks_list, action, invalid_action=None):
function action_has_nla_track (line 197) | def action_has_nla_track(ob, action):
function is_matching_track (line 211) | def is_matching_track(nla_track_type, nla_track, track):
function is_useable_nla_track (line 231) | def is_useable_nla_track(animation_data, nla_track, track):
function is_usable_action (line 320) | def is_usable_action(ob, track):
function is_valid_regular_action (line 373) | def is_valid_regular_action(ob, track):
function is_valid_regular_nla_track (line 380) | def is_valid_regular_nla_track(ob, track):
function is_valid_regular_track (line 388) | def is_valid_regular_track(ob, track):
function is_valid_shape_key_action (line 400) | def is_valid_shape_key_action(ob, track):
function is_valid_shape_key_nla_track (line 408) | def is_valid_shape_key_nla_track(ob, track):
function is_valid_shape_key_track (line 416) | def is_valid_shape_key_track(ob, track):
function get_animation_name (line 428) | def get_animation_name(ob, track, export_settings):
function import_tracks (line 442) | def import_tracks(tracks, ob, component):
class TracksList (line 470) | class TracksList(bpy.types.UIList):
method draw_item (line 473) | def draw_item(self, context, layout, data, item, icon, active_data, ac...
class UpdateTrack (line 503) | class UpdateTrack(Operator):
method execute (line 523) | def execute(self, context):
class AddTrackOperator (line 535) | class AddTrackOperator(Operator):
method execute (line 557) | def execute(self, context):
method invoke (line 576) | def invoke(self, context, event):
class RemoveTrackOperator (line 580) | class RemoveTrackOperator(Operator):
method poll (line 586) | def poll(cls, context):
method execute (line 596) | def execute(self, context):
class UpdateTrackContextMenu (line 616) | class UpdateTrackContextMenu(Menu):
method draw (line 620) | def draw(self, context):
class TracksContextMenu (line 730) | class TracksContextMenu(Menu):
method draw (line 734) | def draw(self, context):
class LoopAnimation (line 831) | class LoopAnimation(HubsComponent):
method draw (line 869) | def draw(self, context, layout, panel):
method gather (line 896) | def gather(self, export_settings, object):
method register (line 911) | def register():
method unregister (line 929) | def unregister():
method gather_import (line 948) | def gather_import(cls, gltf, blender_host, component_name, component_v...
method migrate (line 964) | def migrate(self, migration_type, panel_type, instance_version, host, ...
function register_module (line 1038) | def register_module():
function unregister_module (line 1042) | def unregister_module():
FILE: addons/io_hubs_addon/components/definitions/media_frame.py
function is_bone (line 14) | def is_bone(ob):
class MediaFrameGizmo (line 18) | class MediaFrameGizmo(Gizmo):
method _update_offset_matrix (line 30) | def _update_offset_matrix(self):
method draw (line 37) | def draw(self, context):
method draw_select (line 41) | def draw_select(self, context, select_id):
method setup (line 45) | def setup(self):
class MediaFrame (line 51) | class MediaFrame(HubsComponent):
method update_gizmo (line 118) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 134) | def create_gizmo(cls, ob, gizmo_group):
method migrate (line 152) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method register (line 169) | def register():
method unregister (line 173) | def unregister():
method gather (line 176) | def gather(self, export_settings, object):
method draw (line 201) | def draw(self, context, layout, panel):
method gather_import (line 211) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/mirror.py
class Mirror (line 9) | class Mirror(HubsComponent):
method draw (line 29) | def draw(self, context, layout, panel_type):
method create_gizmo (line 38) | def create_gizmo(cls, ob, gizmo_group):
method update_gizmo (line 55) | def update_gizmo(cls, ob, bone, target, gizmo):
FILE: addons/io_hubs_addon/components/definitions/model.py
class Model (line 7) | class Model(HubsComponent):
method migrate (line 22) | def migrate(self, migration_type, panel_type, instance_version, host, ...
FILE: addons/io_hubs_addon/components/definitions/morph_audio_feedback.py
function get_object_shape_keys (line 11) | def get_object_shape_keys(cmp, ob):
function get_shape_keys (line 40) | def get_shape_keys(self, context):
function get_shape_key (line 44) | def get_shape_key(self):
function set_shape_key (line 52) | def set_shape_key(self, value):
class MorphAudioFeedback (line 61) | class MorphAudioFeedback(HubsComponent):
method poll (line 95) | def poll(cls, panel_type, host, ob=None):
method migrate (line 98) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method draw (line 109) | def draw(self, context, layout, panel):
method gather (line 120) | def gather(self, export_settings, object):
FILE: addons/io_hubs_addon/components/definitions/nav_mesh.py
class NavMesh (line 6) | class NavMesh(HubsComponent):
method poll (line 19) | def poll(cls, panel_type, host, ob=None):
method draw (line 22) | def draw(self, context, layout, panel):
method init (line 38) | def init(cls, obj):
method migrate (line 42) | def migrate(self, migration_type, panel_type, instance_version, host, ...
FILE: addons/io_hubs_addon/components/definitions/networked.py
class Networked (line 9) | class Networked(HubsComponent):
method gather (line 18) | def gather(self, export_settings, object):
function migrate_networked (line 24) | def migrate_networked(host):
FILE: addons/io_hubs_addon/components/definitions/particle_emitter.py
class ParticleEmitter (line 13) | class ParticleEmitter(HubsComponent):
method draw (line 110) | def draw(self, context, layout, panel):
method gather (line 125) | def gather(self, export_settings, object):
method migrate (line 139) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method update_gizmo (line 154) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 164) | def create_gizmo(cls, ob, gizmo_group):
method gather_import (line 181) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/pdf.py
class PDF (line 8) | class PDF(HubsComponent):
method gather_name (line 27) | def gather_name(cls):
method create_gizmo (line 31) | def create_gizmo(cls, ob, gizmo_group):
method update_gizmo (line 47) | def update_gizmo(cls, ob, bone, target, gizmo):
FILE: addons/io_hubs_addon/components/definitions/personal_space_invader.py
class PersonalSpaceInvader (line 6) | class PersonalSpaceInvader(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/point_light.py
class PointLight (line 8) | class PointLight(HubsComponent):
method update_gizmo (line 57) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 67) | def create_gizmo(cls, ob, gizmo_group):
FILE: addons/io_hubs_addon/components/definitions/reflection_probe.py
function get_resolutions (line 37) | def get_resolutions(self, context):
function get_resolution (line 50) | def get_resolution(self):
function set_resolution (line 56) | def set_resolution(self, value):
function get_probes (line 62) | def get_probes(all_objects=False, include_locked=False, include_linked=F...
function get_probe_image_path (line 85) | def get_probe_image_path(probe):
function import_menu_draw (line 89) | def import_menu_draw(self, context):
function export_menu_draw (line 94) | def export_menu_draw(self, context):
class ReflectionProbeSceneProps (line 99) | class ReflectionProbeSceneProps(PropertyGroup):
class BakeProbeOperator (line 119) | class BakeProbeOperator(Operator):
method description (line 141) | def description(cls, context, properties):
method poll (line 154) | def poll(cls, context):
method render_post (line 162) | def render_post(self, scene, depsgraph):
method render_cancelled (line 173) | def render_cancelled(self, scene, depsgraph):
method execute (line 177) | def execute(self, context):
method modal (line 243) | def modal(self, context, event):
method restore_render_props (line 333) | def restore_render_props(self):
method setup_probe_render (line 339) | def setup_probe_render(self, context):
class OpenReflectionProbeEnvMap (line 386) | class OpenReflectionProbeEnvMap(OpenImage):
method poll (line 392) | def poll(cls, context):
class ImportReflectionProbeEnvMaps (line 405) | class ImportReflectionProbeEnvMaps(Operator):
method draw (line 422) | def draw(self, context):
method execute (line 436) | def execute(self, context):
method invoke (line 491) | def invoke(self, context, event):
class ExportReflectionProbeEnvMaps (line 497) | class ExportReflectionProbeEnvMaps(Operator):
method draw (line 527) | def draw(self, context):
method execute (line 537) | def execute(self, context):
method invoke (line 568) | def invoke(self, context, event):
class SelectMismatchedReflectionProbes (line 573) | class SelectMismatchedReflectionProbes(Operator):
method execute (line 582) | def execute(self, context):
method invoke (line 605) | def invoke(self, context, event):
class ReflectionProbe (line 649) | class ReflectionProbe(HubsComponent):
method draw (line 670) | def draw(self, context, layout, panel):
method gather (line 747) | def gather(self, export_settings, object):
method gather_import (line 758) | def gather_import(cls, gltf, blender_host, component_name, component_v...
method draw_global (line 783) | def draw_global(cls, context, layout, panel):
method poll (line 852) | def poll(cls, panel_type, host, ob=None):
method register (line 856) | def register():
method unregister (line 871) | def unregister():
FILE: addons/io_hubs_addon/components/definitions/scale_audio_feedback.py
class ScaleAudioFeedback (line 6) | class ScaleAudioFeedback(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/scene_preview_camera.py
function render_post (line 13) | def render_post(scene, depsgraph):
class RenderOperator (line 24) | class RenderOperator(Operator):
method execute (line 31) | def execute(self, context):
class ScenePreviewCamera (line 72) | class ScenePreviewCamera(HubsComponent):
method pre_export (line 85) | def pre_export(self, export_settings, host, ob=None):
method post_export (line 90) | def post_export(self, export_settings, host, ob=None):
method update_gizmo (line 96) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 104) | def create_gizmo(cls, ob, gizmo_group):
method draw (line 119) | def draw(self, context, layout, panel):
method register (line 127) | def register():
method unregister (line 131) | def unregister():
FILE: addons/io_hubs_addon/components/definitions/shadow.py
class Shadow (line 6) | class Shadow(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/simple_water.py
class SimpleWater (line 6) | class SimpleWater(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/skybox.py
class Skybox (line 6) | class Skybox(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/spawner.py
class Spawner (line 8) | class Spawner(HubsComponent):
method gather (line 26) | def gather(self, export_settings, object):
method migrate (line 34) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method gather_import (line 47) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/spoke/background.py
class Background (line 6) | class Background(HubsComponent):
method gather_import (line 14) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/spoke/box_collider.py
class BoxCollider (line 7) | class BoxCollider(HubsComponent):
method gather_import (line 13) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/spoke/spawn_point.py
class SpawnPoint (line 7) | class SpawnPoint(HubsComponent):
method gather_import (line 13) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/spot_light.py
class SpotLight (line 9) | class SpotLight(HubsComponent):
method update_gizmo (line 78) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 88) | def create_gizmo(cls, ob, gizmo_group):
FILE: addons/io_hubs_addon/components/definitions/text.py
class Text (line 10) | class Text(HubsComponent):
method gather (line 204) | def gather(self, export_settings, object):
method gather_import (line 227) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/uv_scroll.py
class UVScroll (line 6) | class UVScroll(HubsComponent):
method poll (line 30) | def poll(cls, panel_type, host, ob=None):
method draw (line 33) | def draw(self, context, layout, panel):
FILE: addons/io_hubs_addon/components/definitions/video.py
class Video (line 10) | class Video(HubsComponent):
method migrate (line 44) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method update_gizmo (line 53) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 63) | def create_gizmo(cls, ob, gizmo_group):
FILE: addons/io_hubs_addon/components/definitions/video_texture_source.py
class VideoTextureSource (line 7) | class VideoTextureSource(HubsComponent):
method poll (line 27) | def poll(cls, panel_type, host, ob=None):
method get_unsupported_host_message (line 38) | def get_unsupported_host_message(cls, panel_type, host, ob=None):
FILE: addons/io_hubs_addon/components/definitions/video_texture_target.py
function filter_on_component (line 13) | def filter_on_component(self, ob):
function get_bones (line 28) | def get_bones(self, context):
function get_bone (line 56) | def get_bone(self):
function set_bone (line 64) | def set_bone(self, value):
class VideoTextureTarget (line 73) | class VideoTextureTarget(HubsComponent):
method draw (line 112) | def draw(self, context, layout, panel):
method gather (line 159) | def gather(self, export_settings, object):
method gather_import (line 170) | def gather_import(cls, gltf, blender_host, component_name, component_v...
FILE: addons/io_hubs_addon/components/definitions/visible.py
class Visible (line 7) | class Visible(HubsComponent):
FILE: addons/io_hubs_addon/components/definitions/waypoint.py
class Waypoint (line 9) | class Waypoint(HubsComponent):
method update_gizmo (line 58) | def update_gizmo(cls, ob, bone, target, gizmo):
method create_gizmo (line 68) | def create_gizmo(cls, ob, gizmo_group):
method migrate (line 84) | def migrate(self, migration_type, panel_type, instance_version, host, ...
FILE: addons/io_hubs_addon/components/gizmos.py
function gizmo_update (line 10) | def gizmo_update(obj, gizmo):
function bone_matrix_world (line 14) | def bone_matrix_world(ob, bone, scaleOverride=None):
class CustomModelGizmo (line 28) | class CustomModelGizmo(Gizmo):
method draw (line 38) | def draw(self, context):
method draw_select (line 41) | def draw_select(self, context, select_id):
method setup (line 44) | def setup(self):
method invoke (line 49) | def invoke(self, context, event):
method modal (line 58) | def modal(self, context, event, tweak):
class HubsGizmoGroup (line 62) | class HubsGizmoGroup(GizmoGroup):
method add_gizmo (line 72) | def add_gizmo(self, ob, host, host_type):
method setup (line 92) | def setup(self, context):
method update_gizmo (line 116) | def update_gizmo(self, component_name, ob, bone, target, gizmo):
method update_object_gizmo (line 120) | def update_object_gizmo(self, component_name, ob, gizmo):
method update_bone_gizmo (line 123) | def update_bone_gizmo(self, component_name, ob, bone, pose_bone, gizmo):
method refresh (line 126) | def refresh(self, context):
function msgbus_callback (line 162) | def msgbus_callback(*args):
function undo_post (line 167) | def undo_post(dummy):
function redo_post (line 172) | def redo_post(dummy):
function depsgraph_update_post (line 177) | def depsgraph_update_post(dummy):
function load_post (line 207) | def load_post(dummy):
function register_gizmo_system (line 214) | def register_gizmo_system():
function register_gizmos (line 239) | def register_gizmos():
function unregister_gizmo_system (line 249) | def unregister_gizmo_system():
function unregister_gizmos (line 268) | def unregister_gizmos():
function update_gizmos (line 276) | def update_gizmos():
function register_functions (line 282) | def register_functions():
FILE: addons/io_hubs_addon/components/handlers.py
function migrate (line 19) | def migrate(component, migration_type, panel_type, host, migration_repor...
function migrate_components (line 54) | def migrate_components(
function version_beta_components (line 184) | def version_beta_components():
function handle_beta_versioning (line 205) | def handle_beta_versioning():
function load_post (line 221) | def load_post(dummy):
function find_active_undo_step_index (line 235) | def find_active_undo_step_index(undo_steps):
function undo_stack_handler (line 247) | def undo_stack_handler(dummy, depsgraph):
function scene_and_view_layer_update_notifier (line 364) | def scene_and_view_layer_update_notifier(self, context):
function register_msgbus (line 378) | def register_msgbus():
function register (line 395) | def register():
function unregister (line 415) | def unregister():
FILE: addons/io_hubs_addon/components/hubs_component.py
class HubsComponent (line 7) | class HubsComponent(PropertyGroup):
method __get_definition (line 33) | def __get_definition(cls, key, default):
method get_id (line 39) | def get_id(cls):
method get_name (line 44) | def get_name(cls):
method get_display_name (line 48) | def get_display_name(cls, default=None):
method get_node_type (line 53) | def get_node_type(cls):
method get_panel_type (line 57) | def get_panel_type(cls):
method get_category (line 61) | def get_category(cls):
method get_category_name (line 65) | def get_category_name(cls):
method get_definition_version (line 69) | def get_definition_version(cls):
method init (line 73) | def init(cls, obj):
method init_instance_version (line 78) | def init_instance_version(cls, obj):
method create_gizmo (line 83) | def create_gizmo(cls, obj, gizmo_group):
method update_gizmo (line 87) | def update_gizmo(cls, obj, bone, target, gizmo):
method get_deps (line 92) | def get_deps(cls):
method get_icon (line 96) | def get_icon(cls):
method is_dep_only (line 100) | def is_dep_only(cls):
method __init__ (line 103) | def __init__(self, *args, **kwargs):
method draw (line 109) | def draw(self, context, layout, panel):
method pre_export (line 115) | def pre_export(self, export_settings, host, ob=None):
method gather (line 119) | def gather(self, export_settings, object):
method gather_import (line 125) | def gather_import(cls, gltf, blender_host, component_name, component_v...
method post_export (line 132) | def post_export(self, export_settings, host, ob=None):
method migrate (line 136) | def migrate(self, migration_type, panel_type, instance_version, host, ...
method gather_name (line 149) | def gather_name(cls):
method draw_global (line 153) | def draw_global(cls, context, layout, panel):
method get_properties (line 157) | def get_properties(cls):
method poll (line 166) | def poll(cls, panel_type, host, ob=None):
method get_unsupported_host_message (line 173) | def get_unsupported_host_message(cls, panel_type, host, ob=None):
method register (line 185) | def register():
method unregister (line 191) | def unregister():
FILE: addons/io_hubs_addon/components/operators.py
class AddHubsComponent (line 17) | class AddHubsComponent(Operator):
method poll (line 27) | def poll(cls, context):
method execute (line 58) | def execute(self, context):
method invoke (line 70) | def invoke(self, context, event):
class RemoveHubsComponent (line 206) | class RemoveHubsComponent(Operator):
method poll (line 215) | def poll(cls, context):
method execute (line 246) | def execute(self, context):
class MigrateHubsComponents (line 258) | class MigrateHubsComponents(Operator):
method execute (line 267) | def execute(self, context):
class UpdateHubsGizmos (line 277) | class UpdateHubsGizmos(Operator):
method execute (line 282) | def execute(self, context):
class ViewLastReport (line 287) | class ViewLastReport(Operator):
method poll (line 293) | def poll(cls, context):
method execute (line 297) | def execute(self, context):
class ViewReportInInfoEditor (line 306) | class ViewReportInInfoEditor(Operator):
method highlight_info_report (line 314) | def highlight_info_report(self):
method execute (line 331) | def execute(self, context):
class ReportScroller (line 342) | class ReportScroller(Operator):
method description (line 350) | def description(self, context, properties):
method invoke (line 356) | def invoke(self, context, event):
class ReportViewer (line 382) | class ReportViewer(Operator):
method draw (line 389) | def draw(self, context):
method execute (line 447) | def execute(self, context):
method init_report_display_blocks (line 450) | def init_report_display_blocks(self):
method invoke (line 498) | def invoke(self, context, event):
function split_and_prefix_report_messages (line 511) | def split_and_prefix_report_messages(report_string):
class CopyHubsComponent (line 515) | class CopyHubsComponent(Operator):
method poll (line 524) | def poll(cls, context):
method get_selected_bones (line 538) | def get_selected_bones(self, context):
method get_selected_hosts (line 553) | def get_selected_hosts(self, context):
method execute (line 563) | def execute(self, context):
class OpenImage (line 604) | class OpenImage(Operator):
method description (line 622) | def description(cls, context, properties):
method poll (line 630) | def poll(cls, context):
method execute (line 639) | def execute(self, context):
method invoke (line 662) | def invoke(self, context, event):
function register (line 673) | def register():
function unregister (line 692) | def unregister():
FILE: addons/io_hubs_addon/components/types.py
class PanelType (line 4) | class PanelType(Enum):
class NodeType (line 11) | class NodeType(Enum):
class Category (line 17) | class Category(Enum):
class MigrationType (line 29) | class MigrationType(Enum):
FILE: addons/io_hubs_addon/components/ui.py
function draw_component_global (line 8) | def draw_component_global(panel, context):
function draw_component (line 15) | def draw_component(panel, context, obj, row, component_item):
function draw_components_list (line 92) | def draw_components_list(panel, context):
function add_link_indicator (line 115) | def add_link_indicator(layout, datablock):
class HubsObjectPanel (line 134) | class HubsObjectPanel(bpy.types.Panel):
method draw (line 141) | def draw(self, context):
class HUBS_PT_ToolsPanel (line 145) | class HUBS_PT_ToolsPanel(bpy.types.Panel):
method draw (line 153) | def draw(self, context):
class HubsScenePanel (line 157) | class HubsScenePanel(bpy.types.Panel):
method draw (line 164) | def draw(self, context):
class HubsMaterialPanel (line 171) | class HubsMaterialPanel(bpy.types.Panel):
method draw (line 178) | def draw(self, context):
class HubsBonePanel (line 182) | class HubsBonePanel(bpy.types.Panel):
method draw (line 189) | def draw(self, context):
class TooltipLabel (line 193) | class TooltipLabel(bpy.types.Operator):
method description (line 200) | def description(cls, context, properties):
method execute (line 203) | def execute(self, context):
function window_menu_addition (line 207) | def window_menu_addition(self, context):
function object_menu_addition (line 213) | def object_menu_addition(self, context):
function gizmo_display_popover_addition (line 220) | def gizmo_display_popover_addition(self, context):
function register (line 226) | def register():
function unregister (line 239) | def unregister():
FILE: addons/io_hubs_addon/components/utils.py
function add_component (line 17) | def add_component(obj, component_name):
function remove_component (line 38) | def remove_component(obj, component_name):
function get_objects_with_component (line 59) | def get_objects_with_component(component_name):
function has_component (line 63) | def has_component(obj, component_name):
function has_components (line 68) | def has_components(obj, component_names):
function is_dep_required (line 76) | def is_dep_required(obj, component_name, dep_name):
function get_object_source (line 90) | def get_object_source(context, panel_type):
function children_recurse (line 101) | def children_recurse(ob, result):
function children_recursive (line 107) | def children_recursive(ob):
function is_gpu_available (line 116) | def is_gpu_available(context):
function redraw_component_ui (line 121) | def redraw_component_ui(context):
function is_linked (line 128) | def is_linked(datablock):
function update_image_editors (line 134) | def update_image_editors(old_img, img):
class _FILE (line 144) | class _FILE(ctypes.Structure):
function c_fflush (line 157) | def c_fflush():
function c_fflush (line 166) | def c_fflush():
function c_fflush (line 176) | def c_fflush():
function c_fflush (line 190) | def c_fflush():
function c_fflush (line 200) | def c_fflush():
function c_fflush (line 207) | def c_fflush():
function redirect_c_stdout (line 212) | def redirect_c_stdout(binary_stream):
function get_host_components (line 238) | def get_host_components(host):
function wrap_text (line 252) | def wrap_text(text, max_length=70):
function display_wrapped_text (line 283) | def display_wrapped_text(layout, wrapped_text, *, heading_icon='NONE'):
function get_host_reference_message (line 297) | def get_host_reference_message(panel_type, host, ob=None):
function get_host_or_parents_scaled (line 308) | def get_host_or_parents_scaled(obj):
function register (line 327) | def register():
function unregister (line 333) | def unregister():
FILE: addons/io_hubs_addon/debugger.py
function export_scene (line 16) | def export_scene(context):
function is_instance_set (line 44) | def is_instance_set(context):
function is_room_set (line 49) | def is_room_set(context):
class HubsUpdateRoomOperator (line 54) | class HubsUpdateRoomOperator(bpy.types.Operator):
method description (line 60) | def description(cls, context, properties):
method poll (line 72) | def poll(cls, context: Context):
method execute (line 75) | def execute(self, context):
class HubsCreateRoomOperator (line 135) | class HubsCreateRoomOperator(bpy.types.Operator):
method poll (line 142) | def poll(cls, context: Context):
method execute (line 145) | def execute(self, context):
class HubsOpenRoomOperator (line 166) | class HubsOpenRoomOperator(bpy.types.Operator):
method poll (line 173) | def poll(cls, context: Context):
method execute (line 176) | def execute(self, context):
class HubsCloseRoomOperator (line 204) | class HubsCloseRoomOperator(bpy.types.Operator):
method poll (line 211) | def poll(cls, context: Context):
method execute (line 214) | def execute(self, context):
class HubsOpenAddonPrefsOperator (line 225) | class HubsOpenAddonPrefsOperator(bpy.types.Operator):
method poll (line 232) | def poll(cls, context: Context):
method execute (line 235) | def execute(self, context):
class HUBS_PT_ToolsSceneDebuggerCreatePanel (line 243) | class HUBS_PT_ToolsSceneDebuggerCreatePanel(bpy.types.Panel):
method poll (line 252) | def poll(cls, context: Context):
method draw (line 255) | def draw(self, context: Context):
class HUBS_PT_ToolsSceneDebuggerOpenPanel (line 274) | class HUBS_PT_ToolsSceneDebuggerOpenPanel(bpy.types.Panel):
method poll (line 283) | def poll(cls, context: Context):
method draw (line 286) | def draw(self, context: Context):
class HUBS_PT_ToolsSceneDebuggerUpdatePanel (line 306) | class HUBS_PT_ToolsSceneDebuggerUpdatePanel(bpy.types.Panel):
method poll (line 315) | def poll(cls, context: Context):
method draw (line 318) | def draw(self, context: Context):
class HUBS_PT_ToolsSceneSessionPanel (line 381) | class HUBS_PT_ToolsSceneSessionPanel(bpy.types.Panel):
method draw (line 389) | def draw(self, context):
class HUBS_PT_ToolsSceneDebuggerPanel (line 457) | class HUBS_PT_ToolsSceneDebuggerPanel(bpy.types.Panel):
method poll (line 466) | def poll(cls, context: Context):
method draw (line 469) | def draw(self, context):
function add_instance (line 500) | def add_instance(context):
class HubsSceneDebuggerInstanceAdd (line 511) | class HubsSceneDebuggerInstanceAdd(bpy.types.Operator):
method execute (line 516) | def execute(self, context):
class HubsSceneDebuggerInstanceRemove (line 522) | class HubsSceneDebuggerInstanceRemove(bpy.types.Operator):
method execute (line 527) | def execute(self, context):
class HubsSceneDebuggerRoomAdd (line 539) | class HubsSceneDebuggerRoomAdd(bpy.types.Operator):
method execute (line 547) | def execute(self, context):
class HubsSceneDebuggerRoomRemove (line 574) | class HubsSceneDebuggerRoomRemove(bpy.types.Operator):
method poll (line 580) | def poll(cls, context: Context):
method execute (line 584) | def execute(self, context):
class HUBS_UL_ToolsSceneDebuggerServers (line 596) | class HUBS_UL_ToolsSceneDebuggerServers(bpy.types.UIList):
method draw_item (line 600) | def draw_item(self, context, layout, data, item, icon, active_data, ac...
class HUBS_UL_ToolsSceneDebuggerRooms (line 606) | class HUBS_UL_ToolsSceneDebuggerRooms(bpy.types.UIList):
method draw_item (line 610) | def draw_item(self, context, layout, data, item, icon, active_data, ac...
class HubsPublishSceneOperator (line 616) | class HubsPublishSceneOperator(bpy.types.Operator):
method poll (line 623) | def poll(cls, context: Context):
method execute (line 627) | def execute(self, context):
class HubsUpdateSceneOperator (line 685) | class HubsUpdateSceneOperator(bpy.types.Operator):
method poll (line 692) | def poll(cls, context: Context):
method execute (line 695) | def execute(self, context):
method invoke (line 726) | def invoke(self, context, event):
class HubsCreateRoomWithSceneOperator (line 739) | class HubsCreateRoomWithSceneOperator(bpy.types.Operator):
method poll (line 746) | def poll(cls, context: Context):
method execute (line 749) | def execute(self, context):
class HubsGetScenesOperator (line 800) | class HubsGetScenesOperator(bpy.types.Operator):
method poll (line 807) | def poll(cls, context: Context):
method execute (line 810) | def execute(self, context):
class HUBS_UL_ToolsSceneDebuggerProjects (line 840) | class HUBS_UL_ToolsSceneDebuggerProjects(bpy.types.UIList):
method filter_items (line 844) | def filter_items(self, context: Context, data: AnyType, property: str):
method draw_item (line 857) | def draw_item(self, context, layout, data, item, icon, active_data, ac...
class HUBS_PT_ToolsSceneDebuggerPublishScenePanel (line 863) | class HUBS_PT_ToolsSceneDebuggerPublishScenePanel(bpy.types.Panel):
method poll (line 872) | def poll(cls, context: Context):
method draw (line 875) | def draw(self, context: Context):
class HubsSceneDebuggerRoomCreatePrefs (line 926) | class HubsSceneDebuggerRoomCreatePrefs(bpy.types.PropertyGroup):
class HubsSceneDebuggerRoomExportPrefs (line 940) | class HubsSceneDebuggerRoomExportPrefs(bpy.types.PropertyGroup):
class HubsSceneProject (line 988) | class HubsSceneProject(bpy.types.PropertyGroup):
class HubsSceneDebuggerScenePublishProps (line 1021) | class HubsSceneDebuggerScenePublishProps(bpy.types.PropertyGroup):
function save_prefs_on_prop_update (line 1034) | def save_prefs_on_prop_update(self, context):
class HubsSceneDebuggerScenes (line 1038) | class HubsSceneDebuggerScenes(bpy.types.PropertyGroup):
function set_url (line 1050) | def set_url(self, value):
function get_url (line 1060) | def get_url(self):
class HubsUrl (line 1064) | class HubsUrl(bpy.types.PropertyGroup):
class HubsSceneDebuggerPrefs (line 1071) | class HubsSceneDebuggerPrefs(bpy.types.PropertyGroup):
function init (line 1085) | def init():
function load_post (line 1098) | def load_post(dummy):
function update_session (line 1103) | def update_session():
function register (line 1141) | def register():
function unregister (line 1165) | def unregister():
FILE: addons/io_hubs_addon/dependencies/__init__.py
function get_selenium (line 6) | def get_selenium():
FILE: addons/io_hubs_addon/hubs_session.py
class HubsSession (line 80) | class HubsSession:
method init (line 89) | def init(self, context):
method close (line 101) | def close(self):
method __create_instance (line 116) | def __create_instance(self, context):
method update_session_state (line 156) | def update_session_state(self):
method bring_to_front (line 192) | def bring_to_front(self, context):
method is_alive (line 203) | def is_alive(self):
method update (line 212) | def update(self):
method get_local_storage (line 218) | def get_local_storage(self, item):
method set_local_storage (line 225) | def set_local_storage(self, data):
method get_url (line 229) | def get_url(self):
method url_params_string_from_prefs (line 232) | def url_params_string_from_prefs(self, context):
method _get_env_meta (line 243) | def _get_env_meta(self, name):
method get_token (line 246) | def get_token(self):
method set_credentials (line 260) | def set_credentials(self, email, token):
method set_creator_assignment_token (line 273) | def set_creator_assignment_token(self, hub_id, creator_token, embed_to...
method load (line 310) | def load(self, url):
method is_local_instance (line 313) | def is_local_instance(self):
method move_to_waypoint (line 316) | def move_to_waypoint(self, name):
method user_logged_in (line 320) | def user_logged_in(self):
method user_in_room (line 324) | def user_in_room(self):
method room_name (line 328) | def room_name(self):
method room_params (line 332) | def room_params(self):
method reticulum_url (line 336) | def reticulum_url(self):
method client_url (line 340) | def client_url(self):
FILE: addons/io_hubs_addon/icons.py
function load_icons (line 8) | def load_icons():
function unload_icons (line 20) | def unload_icons():
function get_hubs_icons (line 26) | def get_hubs_icons():
function register (line 34) | def register():
function unregister (line 38) | def unregister():
FILE: addons/io_hubs_addon/io/gltf_exporter.py
function patched_gather_gltf (line 17) | def patched_gather_gltf(exporter, export_settings):
function get_version_string (line 28) | def get_version_string():
function export_callback (line 34) | def export_callback(callback_method, export_settings):
function glTF2_pre_export_callback (line 75) | def glTF2_pre_export_callback(export_settings):
function glTF2_post_export_callback (line 87) | def glTF2_post_export_callback(export_settings):
class glTF2ExportUserExtension (line 104) | class glTF2ExportUserExtension:
method add_excluded_property (line 109) | def add_excluded_property(cls, key):
method remove_excluded_property (line 114) | def remove_excluded_property(cls, key):
method __init__ (line 118) | def __init__(self):
method hubs_gather_gltf_hook (line 128) | def hubs_gather_gltf_hook(self, gltf2_object, export_settings):
method gather_gltf_extensions_hook (line 148) | def gather_gltf_extensions_hook(self, gltf2_plan, export_settings):
method gather_scene_hook (line 151) | def gather_scene_hook(self, gltf2_object, blender_scene, export_settin...
method gather_node_hook (line 158) | def gather_node_hook(self, gltf2_object, blender_object, export_settin...
method gather_material_hook (line 164) | def gather_material_hook(self, gltf2_object, blender_material, export_...
method gather_material_unlit_hook (line 182) | def gather_material_unlit_hook(self, gltf2_object, blender_material, e...
method gather_joint_hook (line 186) | def gather_joint_hook(self, gltf2_object, blender_pose_bone, export_se...
method call_delayed_gathers (line 192) | def call_delayed_gathers(self):
method export_hubs_components (line 198) | def export_hubs_components(self, gltf2_object, blender_object, export_...
class HubsComponentsExtensionProperties (line 234) | class HubsComponentsExtensionProperties(bpy.types.PropertyGroup):
class HubsGLTFExportPanel (line 242) | class HubsGLTFExportPanel(bpy.types.Panel):
method poll (line 253) | def poll(cls, context):
method draw_header (line 258) | def draw_header(self, context):
method draw (line 262) | def draw(self, context):
method draw_body (line 266) | def draw_body(context, layout):
function register (line 277) | def register():
function unregister (line 287) | def unregister():
FILE: addons/io_hubs_addon/io/gltf_importer.py
function call_delayed_gathers (line 26) | def call_delayed_gathers():
function import_hubs_components (line 43) | def import_hubs_components(gltf_node, blender_host, gltf, blender_ob=None):
function add_lightmap (line 70) | def add_lightmap(gltf_material, blender_mat, gltf):
function add_bones (line 97) | def add_bones(gltf):
function store_bones_for_import (line 109) | def store_bones_for_import(gltf, vnode):
function show_import_report (line 125) | def show_import_report():
class glTF2ImportUserExtension (line 137) | class glTF2ImportUserExtension:
method __init__ (line 139) | def __init__(self):
method gather_import_scene_before_hook (line 147) | def gather_import_scene_before_hook(self, gltf_scene, blender_scene, g...
method gather_import_scene_after_nodes_hook (line 165) | def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_sce...
method gather_import_node_after_hook (line 174) | def gather_import_node_after_hook(self, vnode, gltf_node, blender_obje...
method gather_import_image_after_hook (line 186) | def gather_import_image_after_hook(self, gltf_img, blender_image, gltf):
method gather_import_texture_after_hook (line 191) | def gather_import_texture_after_hook(
method gather_import_material_after_hook (line 197) | def gather_import_material_after_hook(self, gltf_material, vertex_colo...
method gather_import_scene_after_animation_hook (line 206) | def gather_import_scene_after_animation_hook(self, gltf_scene, blender...
function patched_BlenderNode_create_object (line 218) | def patched_BlenderNode_create_object(gltf, vnode_id):
function patched_BlenderMaterial_create (line 254) | def patched_BlenderMaterial_create(gltf, material_idx, vertex_color):
function patched_BlenderScene_create (line 266) | def patched_BlenderScene_create(gltf):
class HubsGLTFImportPanel (line 288) | class HubsGLTFImportPanel(bpy.types.Panel):
method poll (line 299) | def poll(cls, context):
method draw_header (line 304) | def draw_header(self, context):
method draw (line 308) | def draw(self, context):
method draw_body (line 312) | def draw_body(context, layout):
class HubsImportProperties (line 323) | class HubsImportProperties(bpy.types.PropertyGroup):
function register (line 331) | def register():
function unregister (line 342) | def unregister():
FILE: addons/io_hubs_addon/io/panels.py
function register_panels (line 6) | def register_panels():
function unregister_panels (line 15) | def unregister_panels():
FILE: addons/io_hubs_addon/io/utils.py
class HubsImageData (line 93) | class HubsImageData(gltf2_io_image_data.ImageData):
method file_extension (line 95) | def file_extension(self):
class HubsExportImage (line 101) | class HubsExportImage(gltf2_blender_image.ExportImage):
method from_blender_image (line 103) | def from_blender_image(image: bpy.types.Image):
method encode (line 109) | def encode(self, mime_type: Optional[str], export_settings) -> Union[T...
method encode_from_image_hdr (line 122) | def encode_from_image_hdr(self, image: bpy.types.Image) -> Union[Tuple...
function gather_image (line 137) | def gather_image(blender_image, export_settings):
function gather_texture (line 182) | def gather_texture(blender_image, export_settings):
function gather_properties (line 212) | def gather_properties(export_settings, object, component):
function gather_property (line 230) | def gather_property(export_settings, blender_object, target, property_na...
function gather_array_property (line 255) | def gather_array_property(export_settings, blender_object, target, prope...
function gather_node_property (line 267) | def gather_node_property(export_settings, blender_object, target, proper...
function gather_joint_property (line 298) | def gather_joint_property(export_settings, blender_object, target, prope...
function gather_material_property (line 326) | def gather_material_property(export_settings, blender_object, target, pr...
function gather_vec_property (line 337) | def gather_vec_property(export_settings, blender_object, target, propert...
function gather_image_property (line 364) | def gather_image_property(export_settings, blender_object, target, prope...
function gather_texture_property (line 376) | def gather_texture_property(export_settings, blender_object, target, pro...
function srgb2lin (line 388) | def srgb2lin(s):
function lin2srgb (line 396) | def lin2srgb(lin):
function gather_color_property (line 404) | def gather_color_property(export_settings, object, component, property_n...
function gather_lightmap_texture_info (line 424) | def gather_lightmap_texture_info(blender_material, export_settings):
function import_image (line 463) | def import_image(gltf, gltf_texture):
function import_all_textures (line 484) | def import_all_textures(gltf):
function import_component (line 496) | def import_component(component_name, blender_object):
function set_color_from_hex (line 507) | def set_color_from_hex(blender_component, property_name, hexcolor):
function assign_property (line 520) | def assign_property(vnodes, blender_component, property_name, property_v...
FILE: addons/io_hubs_addon/nodes/__init__.py
function register (line 4) | def register():
function unregister (line 8) | def unregister():
FILE: addons/io_hubs_addon/nodes/lightmap.py
class MozCategory (line 8) | class MozCategory(NodeCategory):
method poll (line 10) | def poll(cls, context):
function add_node_menu_blender4 (line 21) | def add_node_menu_blender4(self, context):
class NODE_MT_moz_nodes (line 25) | class NODE_MT_moz_nodes(bpy.types.Menu):
method draw (line 30) | def draw(self, context):
class MozLightmapNode (line 37) | class MozLightmapNode(Node):
method init (line 48) | def init(self, context):
method poll (line 55) | def poll(cls, ntree):
method draw_buttons (line 58) | def draw_buttons(self, context, layout):
method draw_label (line 61) | def draw_label(self):
function register_blender_4 (line 65) | def register_blender_4():
function unregister_blender_4 (line 71) | def unregister_blender_4():
function register_blender_3 (line 77) | def register_blender_3():
function unregister_blender_3 (line 82) | def unregister_blender_3():
function register (line 87) | def register():
function unregister (line 94) | def unregister():
FILE: addons/io_hubs_addon/preferences.py
function get_addon_pref (line 12) | def get_addon_pref(context):
function get_recast_lib_path (line 17) | def get_recast_lib_path():
class DepsProperty (line 31) | class DepsProperty(bpy.types.PropertyGroup):
class InstallDepsOperator (line 36) | class InstallDepsOperator(bpy.types.Operator):
method execute (line 43) | def execute(self, context):
class UninstallDepsOperator (line 97) | class UninstallDepsOperator(bpy.types.Operator):
method execute (line 104) | def execute(self, context):
class DeleteProfileOperator (line 112) | class DeleteProfileOperator(bpy.types.Operator):
method poll (line 121) | def poll(cls, context: Context):
method execute (line 130) | def execute(self, context):
function set_prefs_dirty (line 140) | def set_prefs_dirty(self, context):
class HubsUserComponentsPath (line 144) | class HubsUserComponentsPath(bpy.types.PropertyGroup):
class HubsUserComponentsPathAdd (line 157) | class HubsUserComponentsPathAdd(bpy.types.Operator):
method execute (line 163) | def execute(self, context):
class HubsUserComponentsPathRemove (line 173) | class HubsUserComponentsPathRemove(bpy.types.Operator):
method execute (line 180) | def execute(self, context):
function draw_user_modules_path_panel (line 190) | def draw_user_modules_path_panel(context, layout, prefs):
class HubsPreferences (line 235) | class HubsPreferences(AddonPreferences):
method draw (line 270) | def draw(self, context):
function register (line 342) | def register():
function unregister (line 353) | def unregister():
FILE: addons/io_hubs_addon/third_party/__init__.py
function register (line 4) | def register():
function unregister (line 8) | def unregister():
FILE: addons/io_hubs_addon/third_party/recast.py
function swap (line 60) | def swap(vec):
function reswap (line 64) | def reswap(vec):
class RecastData (line 68) | class RecastData(ctypes.Structure):
class recast_polyMesh (line 86) | class recast_polyMesh(ctypes.Structure):
class recast_polyMeshDetail (line 107) | class recast_polyMeshDetail(ctypes.Structure):
class recast_polyMesh_holder (line 116) | class recast_polyMesh_holder(ctypes.Structure):
class recast_polyMeshDetail_holder (line 120) | class recast_polyMeshDetail_holder(ctypes.Structure):
function recastDataFromBlender (line 124) | def recastDataFromBlender(scene):
function object_has_collection (line 150) | def object_has_collection(ob, groupName):
function objects_from_collection (line 157) | def objects_from_collection(allObjects, collectionName):
function extractTriangulatedInputMeshList (line 167) | def extractTriangulatedInputMeshList(objects, matrix, verts_offset, vert...
function extractTriangulatedInputMesh (line 206) | def extractTriangulatedInputMesh(context):
function createMesh (line 215) | def createMesh(context, dmesh_holder, obj=None):
function get_auto_cell_size (line 286) | def get_auto_cell_size(context):
class RecastNavMeshResetOperator (line 306) | class RecastNavMeshResetOperator(bpy.types.Operator):
method poll (line 313) | def poll(cls, context):
method execute (line 321) | def execute(self, context):
class RecastNavMeshGenerateOperator (line 344) | class RecastNavMeshGenerateOperator(bpy.types.Operator):
method poll (line 351) | def poll(cls, context):
method execute (line 359) | def execute(self, context):
class RecastNavMeshPropertyGroup (line 455) | class RecastNavMeshPropertyGroup(PropertyGroup):
class RecastAdvancedNavMeshPanel (line 579) | class RecastAdvancedNavMeshPanel(bpy.types.Panel):
method draw (line 588) | def draw(self, context):
class RecastNavMeshPanel (line 607) | class RecastNavMeshPanel(Panel):
method draw (line 615) | def draw(self, context):
function register (line 651) | def register():
function unregister (line 657) | def unregister():
FILE: addons/io_hubs_addon/utils.py
function get_addon_package (line 4) | def get_addon_package():
function rsetattr (line 8) | def rsetattr(obj, attr, val):
function rgetattr (line 13) | def rgetattr(obj, attr, *args):
function delayed_gather (line 19) | def delayed_gather(func):
function get_or_create_deps_path (line 29) | def get_or_create_deps_path(name):
function is_module_available (line 38) | def is_module_available(name, local_dependency=True):
function load_dependency (line 69) | def load_dependency(name):
function get_prefs_dir_path (line 103) | def get_prefs_dir_path():
function create_prefs_dir (line 110) | def create_prefs_dir():
function get_browser_profile_directory (line 117) | def get_browser_profile_directory(browser):
function get_prefs_path (line 131) | def get_prefs_path():
function save_prefs (line 138) | def save_prefs(context):
function load_prefs (line 198) | def load_prefs(context):
function find_area (line 266) | def find_area(area_type):
function image_type_to_file_ext (line 277) | def image_type_to_file_ext(image_type):
function is_addon_enabled (line 294) | def is_addon_enabled():
FILE: scripts/export_gizmo.py
function convert (line 13) | def convert(objects):
class SaveGizmoOperator (line 30) | class SaveGizmoOperator(Operator, ImportHelper):
method execute (line 40) | def execute(self, context):
function register (line 51) | def register():
function unregister (line 55) | def unregister():
FILE: tests/test/test_export.js
constant OUT_PREFIX (line 7) | const OUT_PREFIX = process.env.OUT_PREFIX || '../tests_out';
FILE: tests/test/utils.js
constant UUID_REGEX (line 5) | const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-...
function blenderFileToGltf (line 7) | function blenderFileToGltf(blenderVersion, blenderPath, outDirName, done...
function blenderRoundtripGltf (line 22) | function blenderRoundtripGltf(blenderVersion, gltfPath, outDirName, done...
function validateGltf (line 36) | function validateGltf(gltfPath, done) {
function checkExtensionAdded (line 70) | function checkExtensionAdded(asset, etxName) {
function nodeWithName (line 74) | function nodeWithName(gltf, name) {
function materialWithName (line 83) | function materialWithName(gltf, name) {
FILE: third_parties/recast/app/main.cpp
function main (line 28) | int main(int argc, char *argv[])
FILE: third_parties/recast/app/mesh_navmesh.cpp
function buildNavMesh (line 46) | int buildNavMesh(const RecastData *recastParams, int nverts, float *vert...
function freeNavMesh (line 660) | int freeNavMesh(struct recast_polyMesh_holder *pmeshHolder, struct recas...
FILE: third_parties/recast/app/mesh_navmesh.h
function recast_polyMesh_holder (line 39) | struct RECASTBLENDERADDON_EXPORT recast_polyMesh_holder
function recast_polyMeshDetail_holder (line 44) | struct RECASTBLENDERADDON_EXPORT recast_polyMeshDetail_holder
type recast_polyMesh_holder (line 87) | struct recast_polyMesh_holder
type recast_polyMeshDetail_holder (line 87) | struct recast_polyMeshDetail_holder
type recast_polyMesh_holder (line 91) | struct recast_polyMesh_holder
type recast_polyMeshDetail_holder (line 91) | struct recast_polyMeshDetail_holder
FILE: third_parties/recast/app/recast-capi.cpp
function recast_calcBounds (line 46) | void recast_calcBounds(const float *verts, int nv, float *bmin, float *b...
function recast_calcGridSize (line 51) | void recast_calcGridSize(const float *bmin, const float *bmax, float cs,...
type recast_heightfield (line 56) | struct recast_heightfield
type recast_heightfield (line 58) | struct recast_heightfield
function recast_destroyHeightfield (line 61) | void recast_destroyHeightfield(struct recast_heightfield *heightfield)
function recast_createHeightfield (line 66) | int recast_createHeightfield(struct recast_heightfield *hf, int width, i...
function recast_markWalkableTriangles (line 73) | void recast_markWalkableTriangles(const float walkableSlopeAngle,const f...
function recast_clearUnwalkableTriangles (line 80) | void recast_clearUnwalkableTriangles(const float walkableSlopeAngle, con...
function recast_addSpan (line 87) | int recast_addSpan(struct recast_heightfield *hf, const int x, const int y,
function recast_rasterizeTriangle (line 95) | int recast_rasterizeTriangle(const float *v0, const float *v1, const flo...
function recast_rasterizeTriangles (line 103) | int recast_rasterizeTriangles(const float *verts, const int nv, const in...
function recast_filterLedgeSpans (line 111) | void recast_filterLedgeSpans(const int walkableHeight, const int walkabl...
function recast_filterWalkableLowHeightSpans (line 118) | void recast_filterWalkableLowHeightSpans(int walkableHeight, struct reca...
function recast_filterLowHangingWalkableObstacles (line 124) | void recast_filterLowHangingWalkableObstacles(const int walkableClimb, s...
function recast_getHeightFieldSpanCount (line 130) | int recast_getHeightFieldSpanCount(struct recast_heightfield *hf)
type recast_heightfieldLayerSet (line 136) | struct recast_heightfieldLayerSet
type recast_heightfieldLayerSet (line 138) | struct recast_heightfieldLayerSet
function recast_destroyHeightfieldLayerSet (line 141) | void recast_destroyHeightfieldLayerSet(struct recast_heightfieldLayerSet...
type recast_compactHeightfield (line 146) | struct recast_compactHeightfield
type recast_compactHeightfield (line 148) | struct recast_compactHeightfield
function recast_destroyCompactHeightfield (line 151) | void recast_destroyCompactHeightfield(struct recast_compactHeightfield *...
function recast_buildCompactHeightfield (line 156) | int recast_buildCompactHeightfield(const int walkableHeight, const int w...
function recast_erodeWalkableArea (line 164) | int recast_erodeWalkableArea(int radius, struct recast_compactHeightfiel...
function recast_medianFilterWalkableArea (line 170) | int recast_medianFilterWalkableArea(struct recast_compactHeightfield *chf)
function recast_markBoxArea (line 176) | void recast_markBoxArea(const float *bmin, const float *bmax, unsigned c...
function recast_markConvexPolyArea (line 183) | void recast_markConvexPolyArea(const float* verts, const int nverts,
function recast_offsetPoly (line 191) | int recast_offsetPoly(const float* verts, const int nverts,
function recast_markCylinderArea (line 197) | void recast_markCylinderArea(const float* pos, const float r, const floa...
function recast_buildDistanceField (line 204) | int recast_buildDistanceField(struct recast_compactHeightfield *chf)
function recast_buildRegions (line 210) | int recast_buildRegions(struct recast_compactHeightfield *chf,
function recast_buildLayerRegions (line 218) | int recast_buildLayerRegions(struct recast_compactHeightfield *chf,
function recast_buildRegionsMonotone (line 226) | int recast_buildRegionsMonotone(struct recast_compactHeightfield *chf,
type recast_contourSet (line 234) | struct recast_contourSet
type recast_contourSet (line 236) | struct recast_contourSet
function recast_destroyContourSet (line 239) | void recast_destroyContourSet(struct recast_contourSet *contourSet)
function recast_buildContours (line 244) | int recast_buildContours(struct recast_compactHeightfield *chf,
type recast_polyMesh (line 252) | struct recast_polyMesh
function recast_destroyPolyMesh (line 257) | void recast_destroyPolyMesh(struct recast_polyMesh *polyMesh)
function recast_buildPolyMesh (line 262) | int recast_buildPolyMesh(struct recast_contourSet *cset, const int nvp, ...
function recast_mergePolyMeshes (line 268) | int recast_mergePolyMeshes(struct recast_polyMesh **meshes, const int nm...
function recast_copyPolyMesh (line 274) | int recast_copyPolyMesh(const struct recast_polyMesh *src, struct recast...
type recast_polyMesh (line 280) | struct recast_polyMesh
function recast_polyMeshGetBoundbox (line 290) | void recast_polyMeshGetBoundbox(struct recast_polyMesh *mesh, float *bmi...
function recast_polyMeshGetCell (line 307) | void recast_polyMeshGetCell(struct recast_polyMesh *mesh, float *cs, flo...
type recast_polyMesh (line 318) | struct recast_polyMesh
type recast_polyMeshDetail (line 331) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 333) | struct recast_polyMeshDetail
function recast_destroyPolyMeshDetail (line 336) | void recast_destroyPolyMeshDetail(struct recast_polyMeshDetail *polyMesh...
function recast_buildPolyMeshDetail (line 341) | int recast_buildPolyMeshDetail(const struct recast_polyMesh *mesh, const...
function recast_mergePolyMeshDetails (line 349) | int recast_mergePolyMeshDetails(struct recast_polyMeshDetail **meshes, c...
type recast_polyMeshDetail (line 355) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 365) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 375) | struct recast_polyMeshDetail
FILE: third_parties/recast/app/recast-capi.h
type RECASTBLENDERADDON_EXPORT (line 41) | struct RECASTBLENDERADDON_EXPORT
type RECASTBLENDERADDON_EXPORT (line 42) | struct RECASTBLENDERADDON_EXPORT
type RECASTBLENDERADDON_EXPORT (line 43) | struct RECASTBLENDERADDON_EXPORT
type RECASTBLENDERADDON_EXPORT (line 44) | struct RECASTBLENDERADDON_EXPORT
type RECASTBLENDERADDON_EXPORT (line 45) | struct RECASTBLENDERADDON_EXPORT
type RECASTBLENDERADDON_EXPORT (line 46) | struct RECASTBLENDERADDON_EXPORT
type RECASTBLENDERADDON_EXPORT (line 87) | enum RECASTBLENDERADDON_EXPORT
type recast_heightfield (line 102) | struct recast_heightfield
type recast_heightfield (line 104) | struct recast_heightfield
type recast_heightfield (line 113) | struct recast_heightfield
type recast_heightfield (line 118) | struct recast_heightfield
type recast_heightfield (line 122) | struct recast_heightfield
type recast_heightfield (line 126) | struct recast_heightfield
type recast_heightfield (line 128) | struct recast_heightfield
type recast_heightfield (line 130) | struct recast_heightfield
type recast_heightfield (line 132) | struct recast_heightfield
type recast_heightfieldLayerSet (line 136) | struct recast_heightfieldLayerSet
type recast_compactHeightfield (line 140) | struct recast_compactHeightfield
type recast_heightfield (line 143) | struct recast_heightfield
type recast_compactHeightfield (line 143) | struct recast_compactHeightfield
type recast_compactHeightfield (line 145) | struct recast_compactHeightfield
type recast_compactHeightfield (line 147) | struct recast_compactHeightfield
type recast_compactHeightfield (line 150) | struct recast_compactHeightfield
type recast_compactHeightfield (line 154) | struct recast_compactHeightfield
type recast_compactHeightfield (line 160) | struct recast_compactHeightfield
type recast_compactHeightfield (line 162) | struct recast_compactHeightfield
type recast_compactHeightfield (line 164) | struct recast_compactHeightfield
type recast_compactHeightfield (line 167) | struct recast_compactHeightfield
type recast_compactHeightfield (line 170) | struct recast_compactHeightfield
type recast_contourSet (line 177) | struct recast_contourSet
type recast_compactHeightfield (line 179) | struct recast_compactHeightfield
type recast_contourSet (line 180) | struct recast_contourSet
type recast_polyMesh (line 187) | struct recast_polyMesh
type recast_contourSet (line 189) | struct recast_contourSet
type recast_polyMesh (line 189) | struct recast_polyMesh
type recast_polyMesh (line 191) | struct recast_polyMesh
type recast_polyMesh (line 191) | struct recast_polyMesh
type recast_polyMesh (line 193) | struct recast_polyMesh
type recast_polyMesh (line 193) | struct recast_polyMesh
type recast_polyMesh (line 195) | struct recast_polyMesh
type recast_polyMesh (line 197) | struct recast_polyMesh
type recast_polyMesh (line 199) | struct recast_polyMesh
type recast_polyMesh (line 201) | struct recast_polyMesh
type recast_polyMeshDetail (line 207) | struct recast_polyMeshDetail
type recast_polyMesh (line 209) | struct recast_polyMesh
type recast_compactHeightfield (line 209) | struct recast_compactHeightfield
type recast_polyMeshDetail (line 210) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 212) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 212) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 214) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 216) | struct recast_polyMeshDetail
type recast_polyMeshDetail (line 218) | struct recast_polyMeshDetail
FILE: third_parties/recast/recast/Recast/Include/Recast.h
type rcLogCategory (line 27) | enum rcLogCategory
type rcTimerLabel (line 36) | enum rcTimerLabel
function class (line 101) | class rcContext
function class (line 178) | class rcScopedTimer
type rcConfig (line 198) | struct rcConfig
type rcSpan (line 276) | struct rcSpan
type rcSpanPool (line 286) | struct rcSpanPool
type rcHeightfield (line 294) | struct rcHeightfield
type rcCompactCell (line 316) | struct rcCompactCell
type rcCompactSpan (line 323) | struct rcCompactSpan
type rcCompactHeightfield (line 333) | struct rcCompactHeightfield
type rcHeightfieldLayer (line 357) | struct rcHeightfieldLayer
type rcHeightfieldLayerSet (line 379) | struct rcHeightfieldLayerSet
type rcContour (line 388) | struct rcContour
type rcContourSet (line 400) | struct rcContourSet
type rcPolyMesh (line 418) | struct rcPolyMesh
type rcPolyMeshDetail (line 442) | struct rcPolyMeshDetail
type rcBuildContoursFlags (line 564) | enum rcBuildContoursFlags
function T (line 612) | T rcMin(T a, T b) { return a < b ? a : b; }
function T (line 618) | T rcMax(T a, T b) { return a > b ? a : b; }
function T (line 623) | T rcAbs(T a) { return a < 0 ? -a : a; }
function T (line 628) | T rcSqr(T a) { return a*a; }
function T (line 635) | T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); }
function rcVcross (line 650) | inline void rcVcross(float* dest, const float* v1, const float* v2)
function rcVdot (line 661) | inline float rcVdot(const float* v1, const float* v2)
function rcVmad (line 671) | inline void rcVmad(float* dest, const float* v1, const float* v2, const ...
function rcVadd (line 682) | inline void rcVadd(float* dest, const float* v1, const float* v2)
function rcVsub (line 693) | inline void rcVsub(float* dest, const float* v1, const float* v2)
function rcVmin (line 703) | inline void rcVmin(float* mn, const float* v)
function rcVmax (line 713) | inline void rcVmax(float* mx, const float* v)
function rcVcopy (line 723) | inline void rcVcopy(float* dest, const float* v)
function rcVdist (line 734) | inline float rcVdist(const float* v1, const float* v2)
function rcVdistSqr (line 746) | inline float rcVdistSqr(const float* v1, const float* v2)
function rcVnormalize (line 756) | inline void rcVnormalize(float* v)
function rcSetCon (line 1068) | inline void rcSetCon(rcCompactSpan& s, int dir, int i)
function rcGetCon (line 1080) | inline int rcGetCon(const rcCompactSpan& s, int dir)
function rcGetDirOffsetX (line 1090) | inline int rcGetDirOffsetX(int dir)
function rcGetDirOffsetY (line 1100) | inline int rcGetDirOffsetY(int dir)
function rcGetDirForOffset (line 1110) | inline int rcGetDirForOffset(int x, int y)
FILE: third_parties/recast/recast/Recast/Include/RecastAlloc.h
type rcAllocHint (line 29) | enum rcAllocHint
type rcNewTag (line 67) | struct rcNewTag {}
function delete (line 69) | inline void operator delete(void*, const rcNewTag&, void*) {}
type rcSizeType (line 73) | typedef intptr_t rcSizeType;
function construct (line 100) | static void construct(T* p, const T& v) { ::new(rcNewTag(), (void*)p) T(...
function construct (line 101) | static void construct(T* p) { ::new(rcNewTag(), (void*)p) T; }
type T (line 111) | typedef T value_type;
function assign (line 123) | void assign(rcSizeType count, const T& value) { clear(); resize(count, v...
function resize (line 126) | void resize(rcSizeType size) { resize_impl(size, NULL); }
function resize (line 127) | void resize(rcSizeType size, const T& value) { resize_impl(size, &value); }
function clear (line 129) | void clear() { destroy_range(0, m_size); m_size = 0; }
function pop_back (line 132) | void pop_back() { rcAssert(m_size > 0); back().~T(); m_size--; }
function T (line 138) | const T& operator[](rcSizeType i) const { rcAssert(i >= 0 && i < m_size)...
function T (line 141) | const T& front() const { rcAssert(m_size); return m_data[0]; }
function T (line 143) | const T& back() const { rcAssert(m_size); return m_data[m_size - 1]; };
function T (line 145) | const T* data() const { return m_data; }
function T (line 146) | T* data() { return m_data; }
function T (line 148) | T* begin() { return m_data; }
function T (line 149) | T* end() { return m_data + m_size; }
function T (line 150) | const T* begin() const { return m_data; }
function T (line 151) | const T* end() const { return m_data + m_size; }
function explicit (line 280) | explicit rcTempVector(rcSizeType size) : Base(size) {}
function explicit (line 290) | explicit rcPermVector(rcSizeType size) : Base(size) {}
function m_impl (line 303) | rcIntArray(int n) : m_impl(n, 0) {}
function push (line 304) | void push(int item) { m_impl.push_back(item); }
function resize (line 305) | void resize(int size) { m_impl.resize(size); }
function pop (line 306) | int pop()
function const (line 314) | int operator[](int index) const { return m_impl[index]; }
function ptr (line 329) | inline rcScopedDelete(T* p) : ptr(p) {}
function operator (line 334) | inline operator T*() { return ptr; }
FILE: third_parties/recast/recast/Recast/Source/Recast.cpp
function T (line 36) | T* rcNew(rcAllocHint hint) {
function rcDelete (line 45) | void rcDelete(T* ptr) {
function rcSqrt (line 54) | float rcSqrt(float x)
function rcHeightfield (line 97) | rcHeightfield* rcAllocHeightfield()
function rcFreeHeightField (line 127) | void rcFreeHeightField(rcHeightfield* hf)
function rcCompactHeightfield (line 132) | rcCompactHeightfield* rcAllocCompactHeightfield()
function rcFreeCompactHeightfield (line 137) | void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
function rcHeightfieldLayerSet (line 169) | rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
function rcFreeHeightfieldLayerSet (line 173) | void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
function rcContourSet (line 192) | rcContourSet* rcAllocContourSet()
function rcFreeContourSet (line 196) | void rcFreeContourSet(rcContourSet* cset)
function rcPolyMesh (line 223) | rcPolyMesh* rcAllocPolyMesh()
function rcFreePolyMesh (line 227) | void rcFreePolyMesh(rcPolyMesh* pmesh)
function rcPolyMeshDetail (line 258) | rcPolyMeshDetail* rcAllocPolyMeshDetail()
function rcFreePolyMeshDetail (line 265) | void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh)
function rcCalcBounds (line 274) | void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax)
function rcCalcGridSize (line 287) | void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int*...
function rcCreateHeightfield (line 298) | bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, i...
function calcTriNormal (line 317) | static void calcTriNormal(const float* v0, const float* v1, const float*...
function rcMarkWalkableTriangles (line 334) | void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAn...
function rcClearUnwalkableTriangles (line 364) | void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlop...
function rcGetHeightFieldSpanCount (line 385) | int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf)
function rcBuildCompactHeightfield (line 415) | bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight,...
FILE: third_parties/recast/recast/Recast/Source/RecastAlloc.cpp
function rcFreeDefault (line 29) | static void rcFreeDefault(void *ptr)
function rcAllocSetCustom (line 38) | void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc)
function rcFree (line 56) | void rcFree(void* ptr)
FILE: third_parties/recast/recast/Recast/Source/RecastArea.cpp
function rcErodeWalkableArea (line 37) | bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfiel...
function insertSort (line 221) | static void insertSort(unsigned char* a, const int n)
function rcMedianFilterWalkableArea (line 239) | bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
function rcMarkBoxArea (line 316) | void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax,...
function pointInPoly (line 359) | static int pointInPoly(int nvert, const float* verts, const float* p)
function rcMarkConvexPolyArea (line 381) | void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int ...
function rcOffsetPoly (line 446) | int rcOffsetPoly(const float* verts, const int nverts, const float offset,
function rcMarkCylinderArea (line 529) | void rcMarkCylinderArea(rcContext* ctx, const float* pos,
FILE: third_parties/recast/recast/Recast/Source/RecastAssert.cpp
function rcAssertFailSetCustom (line 25) | void rcAssertFailSetCustom(rcAssertFailFunc *assertFailFunc)
function rcAssertFailFunc (line 30) | rcAssertFailFunc* rcAssertFailGetCustom()
FILE: third_parties/recast/recast/Recast/Source/RecastContour.cpp
function getCornerHeight (line 29) | static int getCornerHeight(int x, int y, int i, int dir,
function walkContour (line 104) | static void walkContour(int x, int y, int i,
function distancePtSeg (line 187) | static float distancePtSeg(const int x, const int z,
function simplifyContour (line 210) | static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
function calcAreaOfPolygon2D (line 454) | static int calcAreaOfPolygon2D(const int* verts, const int nverts)
function prev (line 468) | inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; }
function next (line 469) | inline int next(int i, int n) { return i+1 < n ? i+1 : 0; }
function area2 (line 471) | inline int area2(const int* a, const int* b, const int* c)
function xorb (line 480) | inline bool xorb(bool x, bool y)
function left (line 487) | inline bool left(const int* a, const int* b, const int* c)
function leftOn (line 492) | inline bool leftOn(const int* a, const int* b, const int* c)
function collinear (line 497) | inline bool collinear(const int* a, const int* b, const int* c)
function intersectProp (line 505) | static bool intersectProp(const int* a, const int* b, const int* c, cons...
function between (line 517) | static bool between(const int* a, const int* b, const int* c)
function intersect (line 529) | static bool intersect(const int* a, const int* b, const int* c, const in...
function vequal (line 540) | static bool vequal(const int* a, const int* b)
function intersectSegCountour (line 545) | static bool intersectSegCountour(const int* d0, const int* d1, int i, in...
function inCone (line 565) | static bool inCone(int i, int n, const int* verts, const int* pj)
function removeDegenerateSegments (line 580) | static void removeDegenerateSegments(rcIntArray& simplified)
function mergeContours (line 606) | static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
type rcContourHole (line 650) | struct rcContourHole
type rcContourRegion (line 656) | struct rcContourRegion
type rcPotentialDiagonal (line 663) | struct rcPotentialDiagonal
function findLeftMostVertex (line 670) | static void findLeftMostVertex(rcContour* contour, int* minx, int* minz,...
function compareHoles (line 688) | static int compareHoles(const void* va, const void* vb)
function compareDiagDist (line 710) | static int compareDiagDist(const void* va, const void* vb)
function mergeRegionHoles (line 722) | static void mergeRegionHoles(rcContext* ctx, rcContourRegion& region)
function rcBuildContours (line 824) | bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
FILE: third_parties/recast/recast/Recast/Source/RecastFilter.cpp
function rcFilterLowHangingWalkableObstacles (line 36) | void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walka...
function rcFilterLedgeSpans (line 82) | void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const ...
function rcFilterWalkableLowHeightSpans (line 177) | void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, ...
FILE: third_parties/recast/recast/Recast/Source/RecastLayers.cpp
type rcLayerRegion (line 35) | struct rcLayerRegion
function contains (line 47) | static bool contains(const unsigned char* a, const unsigned char an, con...
function addUnique (line 58) | static bool addUnique(unsigned char* a, unsigned char& an, int anMax, un...
function overlapRange (line 72) | inline bool overlapRange(const unsigned short amin, const unsigned short...
type rcLayerSweepSpan (line 80) | struct rcLayerSweepSpan
function rcBuildHeightfieldLayers (line 92) | bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
FILE: third_parties/recast/recast/Recast/Source/RecastMesh.cpp
type rcEdge (line 27) | struct rcEdge
function buildMeshAdjacency (line 34) | static bool buildMeshAdjacency(unsigned short* polys, const int npolys,
function computeVertexHash (line 128) | inline int computeVertexHash(int x, int y, int z)
function addVertex (line 137) | static unsigned short addVertex(unsigned short x, unsigned short y, unsi...
function prev (line 164) | inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; }
function next (line 165) | inline int next(int i, int n) { return i+1 < n ? i+1 : 0; }
function area2 (line 167) | inline int area2(const int* a, const int* b, const int* c)
function xorb (line 176) | inline bool xorb(bool x, bool y)
function left (line 183) | inline bool left(const int* a, const int* b, const int* c)
function leftOn (line 188) | inline bool leftOn(const int* a, const int* b, const int* c)
function collinear (line 193) | inline bool collinear(const int* a, const int* b, const int* c)
function intersectProp (line 201) | static bool intersectProp(const int* a, const int* b, const int* c, cons...
function between (line 213) | static bool between(const int* a, const int* b, const int* c)
function intersect (line 225) | static bool intersect(const int* a, const int* b, const int* c, const in...
function vequal (line 236) | static bool vequal(const int* a, const int* b)
function diagonalie (line 243) | static bool diagonalie(int i, int j, int n, const int* verts, int* indices)
function inCone (line 270) | static bool inCone(int i, int j, int n, const int* verts, int* indices)
function diagonal (line 287) | static bool diagonal(int i, int j, int n, const int* verts, int* indices)
function diagonalieLoose (line 293) | static bool diagonalieLoose(int i, int j, int n, const int* verts, int* ...
function inConeLoose (line 318) | static bool inConeLoose(int i, int j, int n, const int* verts, int* indi...
function diagonalLoose (line 333) | static bool diagonalLoose(int i, int j, int n, const int* verts, int* in...
function triangulate (line 339) | static int triangulate(int n, const int* verts, int* indices, int* tris)
function countPolyVerts (line 453) | static int countPolyVerts(const unsigned short* p, const int nvp)
function uleft (line 461) | inline bool uleft(const unsigned short* a, const unsigned short* b, cons...
function getPolyMergeValue (line 467) | static int getPolyMergeValue(unsigned short* pa, unsigned short* pb,
function mergePolyVerts (line 531) | static void mergePolyVerts(unsigned short* pa, unsigned short* pb, int e...
function pushFront (line 551) | static void pushFront(int v, int* arr, int& an)
function pushBack (line 558) | static void pushBack(int v, int* arr, int& an)
function canRemoveVertex (line 564) | static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsi...
function removeVertex (line 666) | static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigne...
function rcBuildPolyMesh (line 992) | bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, ...
function rcMergePolyMeshes (line 1311) | bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nm...
function rcCopyPolyMesh (line 1489) | bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst)
FILE: third_parties/recast/recast/Recast/Source/RecastMeshDetail.cpp
type rcHeightPatch (line 32) | struct rcHeightPatch
method rcHeightPatch (line 34) | inline rcHeightPatch() : data(0), xmin(0), ymin(0), width(0), height(0...
function vdot2 (line 41) | inline float vdot2(const float* a, const float* b)
function vdistSq2 (line 46) | inline float vdistSq2(const float* p, const float* q)
function vdist2 (line 53) | inline float vdist2(const float* p, const float* q)
function vcross2 (line 58) | inline float vcross2(const float* p1, const float* p2, const float* p3)
function circumCircle (line 67) | static bool circumCircle(const float* p1, const float* p2, const float* p3,
function distPtTri (line 96) | static float distPtTri(const float* p, const float* a, const float* b, c...
function distancePtSeg (line 124) | static float distancePtSeg(const float* pt, const float* p, const float* q)
function distancePtSeg2d (line 148) | static float distancePtSeg2d(const float* pt, const float* p, const floa...
function distToTriMesh (line 169) | static float distToTriMesh(const float* p, const float* verts, const int...
function distToPoly (line 185) | static float distToPoly(int nvert, const float* verts, const float* p)
function getHeight (line 203) | static unsigned short getHeight(const float fx, const float fy, const fl...
type EdgeValues (line 284) | enum EdgeValues
function findEdge (line 290) | static int findEdge(const int* edges, int nedges, int s, int t)
function addEdge (line 301) | static int addEdge(rcContext* ctx, int* edges, int& nedges, const int ma...
function updateLeftFace (line 326) | static void updateLeftFace(int* e, int s, int t, int f)
function overlapSegSeg2d (line 334) | static int overlapSegSeg2d(const float* a, const float* b, const float* ...
function overlapEdges (line 348) | static bool overlapEdges(const float* pts, const int* edges, int nedges,...
function completeFacet (line 363) | static void completeFacet(rcContext* ctx, const float* pts, int npts, in...
function delaunayHull (line 459) | static void delaunayHull(rcContext* ctx, const int npts, const float* pts,
function polyMinExtent (line 536) | static float polyMinExtent(const float* verts, const int nverts)
function prev (line 557) | inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; }
function next (line 558) | inline int next(int i, int n) { return i+1 < n ? i+1 : 0; }
function triangulateHull (line 560) | static void triangulateHull(const int /*nverts*/, const float* verts, co...
function getJitterX (line 628) | inline float getJitterX(const int i)
function getJitterY (line 633) | inline float getJitterY(const int i)
function buildPolyDetail (line 638) | static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
function seedArrayWithPolyCenter (line 883) | static void seedArrayWithPolyCenter(rcContext* ctx, const rcCompactHeigh...
function push3 (line 1016) | static void push3(rcIntArray& queue, int v1, int v2, int v3)
function getHeightData (line 1024) | static void getHeightData(rcContext* ctx, const rcCompactHeightfield& chf,
function getEdgeFlags (line 1141) | static unsigned char getEdgeFlags(const float* va, const float* vb,
function getTriFlags (line 1156) | static unsigned char getTriFlags(const float* va, const float* vb, const...
function rcBuildPolyMeshDetail (line 1171) | bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const...
function rcMergePolyMeshDetails (line 1390) | bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, c...
FILE: third_parties/recast/recast/Recast/Source/RecastRasterization.cpp
function overlapBounds (line 26) | inline bool overlapBounds(const float* amin, const float* amax, const fl...
function overlapInterval (line 35) | inline bool overlapInterval(unsigned short amin, unsigned short amax,
function rcSpan (line 44) | static rcSpan* allocSpan(rcHeightfield& hf)
function freeSpan (line 77) | static void freeSpan(rcHeightfield& hf, rcSpan* ptr)
function addSpan (line 85) | static bool addSpan(rcHeightfield& hf, const int x, const int y,
function rcAddSpan (line 168) | bool rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y,
function dividePoly (line 184) | static void dividePoly(const float* in, int nin,
function rasterizeTri (line 241) | static bool rasterizeTri(const float* v0, const float* v1, const float* v2,
function rcRasterizeTriangle (line 342) | bool rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v...
function rcRasterizeTriangles (line 366) | bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int ...
function rcRasterizeTriangles (line 398) | bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int ...
function rcRasterizeTriangles (line 430) | bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsi...
FILE: third_parties/recast/recast/Recast/Source/RecastRegion.cpp
type LevelStackEntry (line 31) | struct LevelStackEntry
method LevelStackEntry (line 33) | LevelStackEntry(int x_, int y_, int index_) : x(x_), y(y_), index(inde...
function calculateDistanceField (line 40) | static void calculateDistanceField(rcCompactHeightfield& chf, unsigned s...
function floodRegion (line 253) | static bool floodRegion(int x, int y, int i,
type DirtyEntry (line 354) | struct DirtyEntry
method DirtyEntry (line 356) | DirtyEntry(int index_, unsigned short region_, unsigned short distance2_)
function expandRegions (line 362) | static void expandRegions(int maxIter, unsigned short level,
function sortCellsByLevel (line 471) | static void sortCellsByLevel(unsigned short startLevel,
function appendStacks (line 509) | static void appendStacks(const rcTempVector<LevelStackEntry>& srcStack,
type rcRegion (line 522) | struct rcRegion
method rcRegion (line 524) | inline rcRegion(unsigned short i) :
function removeAdjacentNeighbours (line 548) | static void removeAdjacentNeighbours(rcRegion& reg)
function replaceNeighbour (line 566) | static void replaceNeighbour(rcRegion& reg, unsigned short oldId, unsign...
function canMergeWithRegion (line 586) | static bool canMergeWithRegion(const rcRegion& rega, const rcRegion& regb)
function addUniqueFloorRegion (line 606) | static void addUniqueFloorRegion(rcRegion& reg, int n)
function mergeRegions (line 614) | static bool mergeRegions(rcRegion& rega, rcRegion& regb)
function isRegionConnectedToBorder (line 671) | static bool isRegionConnectedToBorder(const rcRegion& reg)
function isSolidEdge (line 683) | static bool isSolidEdge(rcCompactHeightfield& chf, const unsigned short*...
function walkContour (line 700) | static void walkContour(int x, int y, int i, int dir,
function mergeAndFilterRegions (line 789) | static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int...
function addUniqueConnection (line 1036) | static void addUniqueConnection(rcRegion& reg, int n)
function mergeAndFilterLayerRegions (line 1044) | static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea,
function rcBuildDistanceField (line 1254) | bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf)
function paintRectRegion (line 1305) | static void paintRectRegion(int minx, int maxx, int miny, int maxy, unsi...
type rcSweepSpan (line 1326) | struct rcSweepSpan
function rcBuildRegionsMonotone (line 1353) | bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
function rcBuildRegions (line 1526) | bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
function rcBuildLayerRegions (line 1662) | bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf,
Condensed preview — 215 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,217K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug-report-blender-add-on.md",
"chars": 673,
"preview": "---\nname: Bug Report Blender Add-On\nabout: Help improve the Hubs Blender add-on with quality bug-reports\ntitle: ''\nlabel"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 595,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
},
{
"path": ".github/workflows/publish.yml",
"chars": 5476,
"preview": "name: Publish\n\non:\n push:\n branches:\n - master\n paths-ignore: [\"README.md\", \"LICENSE\", \".gitignore\", \".idea\""
},
{
"path": ".github/workflows/roadmap-auto-commenter.yml",
"chars": 701,
"preview": "# When modifying this file, make sure to pass on the update to all repositories. A tool like https://github.com/gruntwo"
},
{
"path": ".gitignore",
"chars": 278,
"preview": "fake_bpy_modules*\n__pycache__\n.DS_Store\nio_scene_gltf2\n\n# Tests\nnode_modules/\nmochawesome-report\ntests_out/\ngenerated_cu"
},
{
"path": ".vscode/launch.json",
"chars": 893,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n //"
},
{
"path": ".vscode/settings.json",
"chars": 531,
"preview": "{\n \"python.autoComplete.extraPaths\": [\n \"./fake_bpy_modules_3.3-20221006\"\n ],\n \"python.formatting.provider\": \"auto"
},
{
"path": "LICENSE",
"chars": 16726,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "Pipfile",
"chars": 165,
"preview": "[[source]]\nname = \"pypi\"\nurl = \"https://pypi.org/simple\"\nverify_ssl = true\n\n[dev-packages]\nfake-bpy-module-2-82 = \"*\"\n\n["
},
{
"path": "README.md",
"chars": 7912,
"preview": "# Hubs Blender Exporter and Importer\n\nThis addon extends the glTF 2.0 exporter to support the `MOZ_hubs_components` and "
},
{
"path": "addons/io_hubs_addon/.pylintrc",
"chars": 17613,
"preview": "[MASTER]\n\n# A comma-separated list of package or module names from where C extensions may\n# be loaded. Extensions are lo"
},
{
"path": "addons/io_hubs_addon/__init__.py",
"chars": 3068,
"preview": "from .utils import create_prefs_dir\nimport sys\nimport bpy\nfrom .io import gltf_exporter, gltf_importer, panels\nfrom . im"
},
{
"path": "addons/io_hubs_addon/api.py",
"chars": 2316,
"preview": "import requests\n\n\ndef create_room(endpoint, token=None, scene_name=None, scene_id=None):\n payload = {}\n if scene_i"
},
{
"path": "addons/io_hubs_addon/components/__init__.py",
"chars": 416,
"preview": "from . import (handlers, gizmos, components_registry, ui, operators, utils)\n\n\ndef register():\n utils.register()\n h"
},
{
"path": "addons/io_hubs_addon/components/components_registry.py",
"chars": 9542,
"preview": "from .types import NodeType\nimport bpy\nfrom bpy.props import BoolProperty, StringProperty, CollectionProperty, PointerPr"
},
{
"path": "addons/io_hubs_addon/components/consts.py",
"chars": 2280,
"preview": "from math import pi\n\nDISTANCE_MODELS = [(\"inverse\", \"Inverse drop off (inverse)\",\n \"Volume will decre"
},
{
"path": "addons/io_hubs_addon/components/definitions/ambient_light.py",
"chars": 949,
"preview": "from bpy.props import FloatVectorProperty, FloatProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import "
},
{
"path": "addons/io_hubs_addon/components/definitions/ammo_shape.py",
"chars": 3524,
"preview": "from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, BoolProperty\nfrom ..hubs_component import HubsCo"
},
{
"path": "addons/io_hubs_addon/components/definitions/audio.py",
"chars": 2317,
"preview": "from ..models import audio\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world\nfrom bpy.props import BoolProperty, "
},
{
"path": "addons/io_hubs_addon/components/definitions/audio_params.py",
"chars": 6388,
"preview": "import bpy\nfrom bpy.props import BoolProperty, FloatProperty, EnumProperty\nfrom ..hubs_component import HubsComponent\nfr"
},
{
"path": "addons/io_hubs_addon/components/definitions/audio_settings.py",
"chars": 4785,
"preview": "import bpy\nfrom bpy.props import FloatProperty, EnumProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types imp"
},
{
"path": "addons/io_hubs_addon/components/definitions/audio_source.py",
"chars": 866,
"preview": "from bpy.props import BoolProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, PanelType, N"
},
{
"path": "addons/io_hubs_addon/components/definitions/audio_target.py",
"chars": 6617,
"preview": "from email.policy import default\nfrom bpy.props import FloatProperty, BoolProperty, PointerProperty, EnumProperty, Strin"
},
{
"path": "addons/io_hubs_addon/components/definitions/audio_zone.py",
"chars": 2357,
"preview": "from bpy.props import BoolProperty\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world\nfrom ..models import box\nfro"
},
{
"path": "addons/io_hubs_addon/components/definitions/billboard.py",
"chars": 672,
"preview": "from bpy.props import BoolProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, NodeType, Pa"
},
{
"path": "addons/io_hubs_addon/components/definitions/directional_light.py",
"chars": 2663,
"preview": "from ..models import directional_light\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world, update_gizmos\nfrom bpy."
},
{
"path": "addons/io_hubs_addon/components/definitions/environment_settings.py",
"chars": 7881,
"preview": "from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, PointerProperty, BoolProperty\nfrom bpy.types imp"
},
{
"path": "addons/io_hubs_addon/components/definitions/fog.py",
"chars": 1770,
"preview": "from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty\nfrom ..hubs_component import HubsComponent\nfrom ."
},
{
"path": "addons/io_hubs_addon/components/definitions/frustrum.py",
"chars": 623,
"preview": "from bpy.props import BoolProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, PanelType, N"
},
{
"path": "addons/io_hubs_addon/components/definitions/hemisphere_light.py",
"chars": 1371,
"preview": "from bpy.props import FloatVectorProperty, FloatProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import "
},
{
"path": "addons/io_hubs_addon/components/definitions/image.py",
"chars": 2978,
"preview": "from ..models import image\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world\nfrom bpy.props import EnumProperty, "
},
{
"path": "addons/io_hubs_addon/components/definitions/link.py",
"chars": 1800,
"preview": "from ..models import link\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world\nfrom bpy.props import StringProperty\n"
},
{
"path": "addons/io_hubs_addon/components/definitions/loop_animation.py",
"chars": 39863,
"preview": "import bpy\nfrom bpy.app.handlers import persistent\nfrom bpy.props import StringProperty, CollectionProperty, IntProperty"
},
{
"path": "addons/io_hubs_addon/components/definitions/media_frame.py",
"chars": 9371,
"preview": "import bpy\nfrom bpy.props import EnumProperty, FloatVectorProperty, BoolProperty\nfrom bpy.types import (Gizmo, Bone, Edi"
},
{
"path": "addons/io_hubs_addon/components/definitions/mirror.py",
"chars": 3276,
"preview": "from bpy.props import FloatVectorProperty\nfrom ..hubs_component import HubsComponent\nfrom ..gizmos import update_gizmos\n"
},
{
"path": "addons/io_hubs_addon/components/definitions/model.py",
"chars": 930,
"preview": "from bpy.props import StringProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, PanelType,"
},
{
"path": "addons/io_hubs_addon/components/definitions/morph_audio_feedback.py",
"chars": 3659,
"preview": "import bpy\nfrom bpy.props import FloatProperty, StringProperty, EnumProperty\nfrom ..hubs_component import HubsComponent\n"
},
{
"path": "addons/io_hubs_addon/components/definitions/nav_mesh.py",
"chars": 1679,
"preview": "from ..hubs_component import HubsComponent\nfrom ..types import Category, PanelType, NodeType\nfrom ..utils import has_com"
},
{
"path": "addons/io_hubs_addon/components/definitions/networked.py",
"chars": 693,
"preview": "from ..hubs_component import HubsComponent\nfrom bpy.props import StringProperty\nfrom ..types import PanelType, NodeType\n"
},
{
"path": "addons/io_hubs_addon/components/definitions/particle_emitter.py",
"chars": 7833,
"preview": "from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, StringProperty, IntProperty\nfrom ..hubs_componen"
},
{
"path": "addons/io_hubs_addon/components/definitions/pdf.py",
"chars": 2831,
"preview": "from bpy.props import StringProperty, BoolProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Catego"
},
{
"path": "addons/io_hubs_addon/components/definitions/personal_space_invader.py",
"chars": 959,
"preview": "from bpy.props import BoolProperty, FloatProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Categor"
},
{
"path": "addons/io_hubs_addon/components/definitions/point_light.py",
"chars": 2920,
"preview": "from ..models import point_light\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world, update_gizmos\nfrom bpy.props "
},
{
"path": "addons/io_hubs_addon/components/definitions/reflection_probe.py",
"chars": 36528,
"preview": "from ..operators import OpenImage\nimport bpy\nfrom bpy.props import PointerProperty, EnumProperty, StringProperty, BoolPr"
},
{
"path": "addons/io_hubs_addon/components/definitions/scale_audio_feedback.py",
"chars": 753,
"preview": "from bpy.props import FloatProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, PanelType, "
},
{
"path": "addons/io_hubs_addon/components/definitions/scene_preview_camera.py",
"chars": 4509,
"preview": "from ..hubs_component import HubsComponent\nfrom ..types import Category, PanelType, NodeType\nfrom ..gizmos import Custom"
},
{
"path": "addons/io_hubs_addon/components/definitions/shadow.py",
"chars": 614,
"preview": "from bpy.props import BoolProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, NodeType, Pa"
},
{
"path": "addons/io_hubs_addon/components/definitions/simple_water.py",
"chars": 2654,
"preview": "from bpy.props import FloatVectorProperty, FloatProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import "
},
{
"path": "addons/io_hubs_addon/components/definitions/skybox.py",
"chars": 1683,
"preview": "from bpy.props import FloatProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, PanelType, "
},
{
"path": "addons/io_hubs_addon/components/definitions/spawner.py",
"chars": 2151,
"preview": "import bpy\nfrom bpy.props import StringProperty, BoolProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types im"
},
{
"path": "addons/io_hubs_addon/components/definitions/spoke/background.py",
"chars": 679,
"preview": "from ....io.utils import import_component, set_color_from_hex\nfrom ...hubs_component import HubsComponent\nfrom ...types "
},
{
"path": "addons/io_hubs_addon/components/definitions/spoke/box_collider.py",
"chars": 1236,
"preview": "from ...types import NodeType\nfrom ...hubs_component import HubsComponent\nfrom ....io.utils import assign_property, impo"
},
{
"path": "addons/io_hubs_addon/components/definitions/spoke/spawn_point.py",
"chars": 566,
"preview": "from ...types import NodeType\nfrom ...hubs_component import HubsComponent\nfrom ...utils import add_component\nfrom ....io"
},
{
"path": "addons/io_hubs_addon/components/definitions/spot_light.py",
"chars": 3682,
"preview": "from ..models import spot_light\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world, update_gizmos\nfrom bpy.props i"
},
{
"path": "addons/io_hubs_addon/components/definitions/text.py",
"chars": 12504,
"preview": "from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, StringProperty\nfrom ..hubs_component import Hubs"
},
{
"path": "addons/io_hubs_addon/components/definitions/uv_scroll.py",
"chars": 1581,
"preview": "from bpy.props import FloatVectorProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, Panel"
},
{
"path": "addons/io_hubs_addon/components/definitions/video.py",
"chars": 2556,
"preview": "from ..models import video\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world\nfrom bpy.props import BoolProperty, "
},
{
"path": "addons/io_hubs_addon/components/definitions/video_texture_source.py",
"chars": 1928,
"preview": "from ..utils import children_recursive, get_host_reference_message\nfrom bpy.props import IntVectorProperty, IntProperty\n"
},
{
"path": "addons/io_hubs_addon/components/definitions/video_texture_target.py",
"chars": 6216,
"preview": "from bpy.props import BoolProperty, PointerProperty, EnumProperty, StringProperty\nfrom ..hubs_component import HubsCompo"
},
{
"path": "addons/io_hubs_addon/components/definitions/visible.py",
"chars": 504,
"preview": "import bpy\nfrom bpy.props import BoolProperty\nfrom ..hubs_component import HubsComponent\nfrom ..types import Category, P"
},
{
"path": "addons/io_hubs_addon/components/definitions/waypoint.py",
"chars": 3170,
"preview": "from ..models import spawn_point\nfrom ..gizmos import CustomModelGizmo, bone_matrix_world\nfrom ..types import Category, "
},
{
"path": "addons/io_hubs_addon/components/gizmos.py",
"chars": 10249,
"preview": "import bpy\nfrom bpy.types import (Gizmo, GizmoGroup)\nfrom bpy.props import (IntProperty)\nfrom .components_registry impor"
},
{
"path": "addons/io_hubs_addon/components/handlers.py",
"chars": 18947,
"preview": "import bpy\nfrom bpy.app.handlers import persistent\nfrom .components_registry import get_components_registry\nfrom .utils "
},
{
"path": "addons/io_hubs_addon/components/hubs_component.py",
"chars": 8609,
"preview": "from bpy.types import PropertyGroup\nfrom bpy.props import IntVectorProperty\nfrom .types import Category, PanelType, Node"
},
{
"path": "addons/io_hubs_addon/components/models/audio.py",
"chars": 23920,
"preview": "SHAPE = ((-0.500000, 0.000000, -0.362840),(0.500000, 0.000000, -0.362840),(0.500000, 0.000000, 0.362840),(-0.500000, 0.0"
},
{
"path": "addons/io_hubs_addon/components/models/box.py",
"chars": 9370,
"preview": "SHAPE = ((0.500000, 0.500000, 0.500000),(-0.500000, 0.500000, 0.500000),(-0.475000, 0.475000, 0.500000),(0.500000, 0.500"
},
{
"path": "addons/io_hubs_addon/components/models/directional_light.py",
"chars": 25643,
"preview": "SHAPE = ((0.000000, 0.181373, 0.036077),(0.128250, 0.128250, -0.036077),(0.000000, 0.181373, -0.036077),(-0.072648, 0.07"
},
{
"path": "addons/io_hubs_addon/components/models/image.py",
"chars": 4888,
"preview": "SHAPE = ((0.179200, -0.003164, 0.143934),(-0.379381, -0.003164, 0.218799),(0.374179, -0.003164, 0.218799),(0.176258, -0."
},
{
"path": "addons/io_hubs_addon/components/models/link.py",
"chars": 19211,
"preview": "SHAPE = ((0.153029, -0.091493, -0.027939),(0.036019, -0.018590, 0.143833),(0.046648, -0.042210, 0.187375),(0.153029, -0."
},
{
"path": "addons/io_hubs_addon/components/models/particle_emitter.py",
"chars": 12775,
"preview": "SHAPE = ((-0.480059, 0.000000, 1.590102),(-0.480059, 0.000000, 1.797271),(-0.272890, 0.000000, 1.797271),(-0.480059, 0.0"
},
{
"path": "addons/io_hubs_addon/components/models/point_light.py",
"chars": 29028,
"preview": "SHAPE = ((-0.000000, 0.226909, 0.131224),(0.173669, 0.173669, 0.037235),(-0.000000, 0.245605, 0.037235),(-0.000000, 0.09"
},
{
"path": "addons/io_hubs_addon/components/models/scene_preview_camera.py",
"chars": 7474,
"preview": "SHAPE = ((0.000000, -0.014454, 0.006692),(-0.939086, -1.070925, 0.495799),(-0.952800, -1.077091, 0.493699),(0.000000, -0"
},
{
"path": "addons/io_hubs_addon/components/models/spawn_point.py",
"chars": 26387,
"preview": "SHAPE = ((0.100819, -0.134342, 1.378268),(-0.100819, -0.117241, 1.378268),(-0.100819, -0.134342, 1.378268),(-0.100819, -"
},
{
"path": "addons/io_hubs_addon/components/models/spot_light.py",
"chars": 21274,
"preview": "SHAPE = ((-0.000000, -0.136614, 0.103780),(-0.000000, -0.273228, 0.213055),(0.081533, -0.273228, 0.196837),(-0.000000, -"
},
{
"path": "addons/io_hubs_addon/components/models/video.py",
"chars": 15298,
"preview": "SHAPE = ((0.301114, -0.005712, 0.153260),(0.429815, -0.005712, 0.132392),(0.429815, -0.005712, 0.153260),(-0.521948, -0."
},
{
"path": "addons/io_hubs_addon/components/operators.py",
"chars": 29552,
"preview": "import bpy\nfrom bpy.props import StringProperty, IntProperty, BoolProperty, CollectionProperty\nfrom bpy.types import Ope"
},
{
"path": "addons/io_hubs_addon/components/types.py",
"chars": 548,
"preview": "from enum import Enum\n\n\nclass PanelType(Enum):\n OBJECT = 'object'\n SCENE = 'scene'\n MATERIAL = 'material'\n B"
},
{
"path": "addons/io_hubs_addon/components/ui.py",
"chars": 7678,
"preview": "import bpy\nfrom bpy.props import StringProperty\nfrom .types import PanelType\nfrom .components_registry import get_compon"
},
{
"path": "addons/io_hubs_addon/components/utils.py",
"chars": 11648,
"preview": "import tempfile\nimport bpy\nfrom .components_registry import get_component_by_name, get_components_registry\nfrom .gizmos "
},
{
"path": "addons/io_hubs_addon/debugger.py",
"chars": 44028,
"preview": "from bpy.app.handlers import persistent\nimport bpy\nfrom bpy.types import Context\n\nfrom .preferences import EXPORT_TMP_FI"
},
{
"path": "addons/io_hubs_addon/dependencies/__init__.py",
"chars": 198,
"preview": "from ..utils import load_dependency\n\nselenium = None\n\n\ndef get_selenium():\n global selenium\n if selenium is None:\n"
},
{
"path": "addons/io_hubs_addon/hubs_session.py",
"chars": 14102,
"preview": "import bpy\nfrom .preferences import get_addon_pref, EXPORT_TMP_FILE_NAME\nfrom .utils import is_module_available, get_bro"
},
{
"path": "addons/io_hubs_addon/icons.py",
"chars": 798,
"preview": "import bpy\nimport os\nfrom os import listdir\nfrom os.path import join, isfile\nimport bpy.utils.previews\n\n\ndef load_icons("
},
{
"path": "addons/io_hubs_addon/io/gltf_exporter.py",
"chars": 11584,
"preview": "import bpy\nfrom .utils import HUBS_CONFIG\nfrom bpy.props import PointerProperty\nfrom ..components.components_registry im"
},
{
"path": "addons/io_hubs_addon/io/gltf_importer.py",
"chars": 13583,
"preview": "import bpy\nimport traceback\nfrom .utils import HUBS_CONFIG, import_image, import_all_textures\nfrom ..components.componen"
},
{
"path": "addons/io_hubs_addon/io/panels.py",
"chars": 575,
"preview": "import bpy\nfrom .gltf_exporter import HubsGLTFExportPanel\nfrom .gltf_importer import HubsGLTFImportPanel\n\n\ndef register_"
},
{
"path": "addons/io_hubs_addon/io/utils.py",
"chars": 21041,
"preview": "import bpy\nimport os\nimport re\nfrom ..nodes.lightmap import MozLightmapNode\nfrom io_scene_gltf2.io.com import gltf2_io_e"
},
{
"path": "addons/io_hubs_addon/nodes/__init__.py",
"chars": 113,
"preview": "from . import (lightmap)\n\n\ndef register():\n lightmap.register()\n\n\ndef unregister():\n lightmap.unregister()\n"
},
{
"path": "addons/io_hubs_addon/nodes/lightmap.py",
"chars": 2451,
"preview": "import bpy\n\nimport nodeitems_utils\nfrom nodeitems_utils import NodeCategory, NodeItem\nfrom bpy.types import Node\n\n\nclass"
},
{
"path": "addons/io_hubs_addon/preferences.py",
"chars": 14056,
"preview": "import bpy\nfrom bpy.types import AddonPreferences, Context\nfrom bpy.props import IntProperty, StringProperty, EnumProper"
},
{
"path": "addons/io_hubs_addon/third_party/__init__.py",
"chars": 107,
"preview": "from . import (recast)\n\n\ndef register():\n recast.register()\n\n\ndef unregister():\n recast.unregister()\n"
},
{
"path": "addons/io_hubs_addon/third_party/recast.py",
"chars": 24799,
"preview": "# ***** BEGIN GPL LICENSE BLOCK *****\n#\n#\n# This program is free software; you can redistribute it and/or\n# modify it un"
},
{
"path": "addons/io_hubs_addon/utils.py",
"chars": 8579,
"preview": "import functools\n\n\ndef get_addon_package():\n return __package__\n\n\ndef rsetattr(obj, attr, val):\n pre, _, post = at"
},
{
"path": "check_style.py",
"chars": 362,
"preview": "import subprocess\nimport sys\nfrom shutil import which\n\nif which(\"pycodestyle\") is None:\n print(\"Error: pycodestyle co"
},
{
"path": "format.py",
"chars": 418,
"preview": "import subprocess\nimport sys\nfrom shutil import which\n\nif which(\"autopep8\") is None:\n print(\"Error: autopep8 could no"
},
{
"path": "scripts/export_gizmo.py",
"chars": 1506,
"preview": "# Blender utility script to export a mesh in the Gizmo format.\n# Usage:\n# Run Blender from the terminal.\n# Create a new "
},
{
"path": "setup.sh",
"chars": 147,
"preview": "wget https://github.com/nutti/fake-bpy-module/releases/download/20221006/fake_bpy_modules_3.3-20221006.zip -O temp.zip; "
},
{
"path": "tests/.eslintrc.json",
"chars": 372,
"preview": "{\n \"extends\": \"eslint:recommended\",\n \"parserOptions\": {\n \"ecmaVersion\": 2017\n },\n \"globals\": {\n \"describe\": \"r"
},
{
"path": "tests/.npmrc",
"chars": 18,
"preview": "package-lock=false"
},
{
"path": "tests/export_gltf.py",
"chars": 1577,
"preview": "# Copyright 2018-2021 The Khronos Group Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you m"
},
{
"path": "tests/package.json",
"chars": 523,
"preview": "{\n \"name\": \"io-hubs-addon-tests\",\n \"version\": \"1.0.0\",\n \"description\": \"Test suite for io-hubs-addon\",\n \"dependencie"
},
{
"path": "tests/roundtrip_gltf.py",
"chars": 2647,
"preview": "# Copyright 2018-2021 The Khronos Group Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you m"
},
{
"path": "tests/test/test_export.js",
"chars": 4398,
"preview": "const fs = require('fs');\nconst glob = require('glob')\nconst path = require('path');\nconst { test } = require('./tests/l"
},
{
"path": "tests/test/tests/ambient-light.js",
"chars": 889,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/ammo-shape.js",
"chars": 1300,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/audio-settings.js",
"chars": 1339,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/audio-target.js",
"chars": 1899,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/audio-zone.js",
"chars": 1313,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/audio.js",
"chars": 1389,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/billboard.js",
"chars": 841,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/directional-light.js",
"chars": 1115,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/environment-settings.js",
"chars": 1257,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/fog.js",
"chars": 968,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/frustrum.js",
"chars": 839,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/hemisphere-light.js",
"chars": 943,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/image.js",
"chars": 1071,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/link.js",
"chars": 869,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/loop-animation.js",
"chars": 1303,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/media-frame.js",
"chars": 1211,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/model.js",
"chars": 907,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/morph-audio-feedback.js",
"chars": 937,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/nav-mesh.js",
"chars": 870,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/particle-emitter.js",
"chars": 1739,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/personal-space-invader.js",
"chars": 989,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/point-light.js",
"chars": 1153,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/scale-audio-feedback.js",
"chars": 906,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/shadow.js",
"chars": 863,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/simple-water.js",
"chars": 1484,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/skybox.js",
"chars": 1122,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/spawner.js",
"chars": 991,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/spot-light.js",
"chars": 1241,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/text.js",
"chars": 1759,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/text_clip-rect.js",
"chars": 2007,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/uv-scroll.js",
"chars": 1015,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/video-texture.js",
"chars": 1683,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/video.js",
"chars": 1423,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/visible.js",
"chars": 784,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/tests/waypoint.js",
"chars": 1142,
"preview": "const fs = require('fs');\nconst path = require('path')\nconst assert = require('assert');\nconst utils = require('../utils"
},
{
"path": "tests/test/utils.js",
"chars": 3092,
"preview": "const fs = require('fs');\nconst path = require('path');\nconst validator = require('gltf-validator');\n\nconst UUID_REGEX ="
},
{
"path": "third_parties/recast/app/CMakeLists.txt",
"chars": 1048,
"preview": "cmake_minimum_required(VERSION 3.5)\n\nset(CMAKE_OSX_ARCHITECTURES \"arm64;x86_64\" CACHE STRING \"\" FORCE)\n\nproject(RecastBl"
},
{
"path": "third_parties/recast/app/main.cpp",
"chars": 3357,
"preview": "/*\n * ***** BEGIN GPL LICENSE BLOCK *****\n *\n * This program is free software; you can redistribute it and/or\n * modify "
},
{
"path": "third_parties/recast/app/mesh_navmesh.cpp",
"chars": 36552,
"preview": "/*\n * ***** BEGIN GPL LICENSE BLOCK *****\n *\n * This program is free software; you can redistribute it and/or\n * modify "
},
{
"path": "third_parties/recast/app/mesh_navmesh.h",
"chars": 3107,
"preview": "/*\n * ***** BEGIN GPL LICENSE BLOCK *****\n *\n * This program is free software; you can redistribute it and/or\n * modify "
},
{
"path": "third_parties/recast/app/recast-capi.cpp",
"chars": 11277,
"preview": "/*\n *\n * ***** BEGIN GPL LICENSE BLOCK *****\n *\n * This program is free software; you can redistribute it and/or\n * modi"
},
{
"path": "third_parties/recast/app/recast-capi.h",
"chars": 10260,
"preview": "/*\n *\n * ***** BEGIN GPL LICENSE BLOCK *****\n *\n * This program is free software; you can redistribute it and/or\n * modi"
},
{
"path": "third_parties/recast/app/recast-capi_global.h",
"chars": 1482,
"preview": "/*\n * ***** BEGIN GPL LICENSE BLOCK *****\n *\n * This program is free software; you can redistribute it and/or\n * modify "
},
{
"path": "third_parties/recast/recast/CMakeLists.txt",
"chars": 270,
"preview": "cmake_minimum_required(VERSION 3.0)\n\nset(CMAKE_OSX_ARCHITECTURES \"arm64;x86_64\" CACHE STRING \"\" FORCE)\n\nproject(RecastNa"
},
{
"path": "third_parties/recast/recast/CONTRIBUTING.md",
"chars": 7587,
"preview": "# Contributing to Recast and Detour\n\nWe'd love for you to contribute to our source code and to make Recast and Detour ev"
},
{
"path": "third_parties/recast/recast/License.txt",
"chars": 859,
"preview": "Copyright (c) 2009 Mikko Mononen memon@inside.org\n\nThis software is provided 'as-is', without any express or implied\nwar"
},
{
"path": "third_parties/recast/recast/README.md",
"chars": 5676,
"preview": "\nRecast & Detour\n===============\n\n[\n\nif (RECASTNAVIGATION_STATIC)\n add_library(Recast STATIC ${SOURCES})\nelse ()\n add_"
},
{
"path": "third_parties/recast/recast/Recast/Include/Recast.h",
"chars": 55603,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Include/RecastAlloc.h",
"chars": 12629,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Include/RecastAssert.h",
"chars": 2242,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/Recast.cpp",
"chars": 13783,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastAlloc.cpp",
"chars": 1834,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastArea.cpp",
"chars": 15659,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastAssert.cpp",
"chars": 1212,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastContour.cpp",
"chars": 30371,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastFilter.cpp",
"chars": 6252,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastLayers.cpp",
"chars": 17349,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastMesh.cpp",
"chars": 42537,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastMeshDetail.cpp",
"chars": 39668,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastRasterization.cpp",
"chars": 11917,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/Recast/Source/RecastRegion.cpp",
"chars": 45746,
"preview": "//\n// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org\n//\n// This software is provided 'as-is', without any expres"
},
{
"path": "third_parties/recast/recast/readme-addon.txt",
"chars": 418,
"preview": "\nThe version of Recast is based on commit 57610fa6ef31b39020231906f8c5d40eaa8294ae (date: 21 Oct 2019) from repository\nh"
}
]
// ... and 49 more files (download for full content)
About this extraction
This page contains the full source code of the MozillaReality/hubs-blender-exporter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 215 files (1.1 MB), approximately 354.0k tokens, and a symbol index with 1092 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.